for C/C++ structs, the binary layout is different from the PNode binary layout
of a compile time object instance, so you can't just deref a ptr Foo returned
by a importc proc (that wouldn't make sense); and thankfully the compiler
prevents it.
However you can access individual fields via accessors. Again, this can be
automated to a large extent using macros that would generate such accessors.
Here's a complete working example, where I show accessors either by value
(get_x1) or by pointer (get_x2_ptr):
when defined(timn_D20191211T153325):
{.emit:"""
#define MAX(a,b) ((a < b) ? (b) : (a))
#define MY_CONST1 "asdf"
#define MY_CONST2 23
typedef struct Foo {
int x1;
double x2;
} Foo;
N_LIB_EXPORT int MAX_int(int a, int b){ return MAX(a, b);}
N_LIB_EXPORT char* get_MY_CONST1(){return MY_CONST1;}
N_LIB_EXPORT int get_MY_CONST2(){return MY_CONST2;}
// example showing returning struct
N_LIB_EXPORT Foo* get_FooPtr(int x1, double x2){Foo* ret =
(Foo*)(malloc(sizeof(Foo))); ret->x1 = x1; ret->x2 = x2; return ret;}
N_LIB_EXPORT int get_x1(Foo*a) {return a->x1;}
N_LIB_EXPORT double* get_x2_ptr(Foo*a) {return &a->x2;}
""".}
else:
import std/[strformat,os,strutils]
const libF = "/tmp/" / (DynlibFormat % "D20191211T153325")
const nim = getCurrentCompilerExe()
const file = currentSourcePath()
static:
when true:
let cmd = fmt"{nim} c -d:timn_D20191211T153325 --app:lib -o:{libF}
{file}"
echo cmd
let (output, exitCode) = gorgeEx cmd
doAssert exitCode == 0, output
proc MAX_int(a, b: int): int {.importc, dynlib: libF.}
proc MY_CONST1(): cstring {.importc: "get_MY_CONST1", dynlib: libF.}
proc MY_CONST2(): cint {.importc: "get_MY_CONST2", dynlib: libF.}
type Foo = object
x1: cint
x2: float
proc get_FooPtr(x1: cint, x2: float): ptr Foo {.importc, dynlib: libF.}
proc get_x1(a: ptr Foo): cint {.importc, dynlib: libF.}
proc get_x2_ptr(a: ptr Foo): ptr float {.importc, dynlib: libF.}
proc main()=
doAssert MAX_int(2, 3) == 3
doAssert MY_CONST1() == "asdf"
doAssert MY_CONST2() == 23
# example showing passing/returning struct (by pointer)
let foo = get_FooPtr(123, 1.5)
doAssert foo.get_x1 == 123
doAssert foo.get_x2_ptr[] == 1.5
foo.get_x2_ptr[] = 2.0
doAssert foo.get_x2_ptr[] == 2.0
static: main()
main()
Run