I want to make a arbitary-integer arithmetic c library with c code generated from Nim. And I want to make a tuple in Nim to store it like:
tuple
isNotNeg : bool
num_seq : seq[cuint]
And it's the example function:
proc example() : HugeNum {.exportc.} =
var s : HugeNum
s = (isNotNeg : true, num_seq : @[32'u32 , 12'u32])
return s
However, when I generated to C header file with nim c --noMain --noLinking --header:xxx.h xxx.nim , the definition of getting a bignum function in the C header file is like:
N_NIMCALL(void, example)(HugeNum* Result);
It says it should take a HugeNum pointer, however the function is non-parameter function.
The function returning only a sequence didn't have the event. Therefore,
proc get_seq2() : seq[cuint] {.exportc.} =
var s : seq[cuint] = @[9'u32]
return s
becomes
N_NIMCALL(tySequence__U48dCdy0noze9bNL2psZZGA*, get_seq2)(void); // takes no argument
Can you give the full example file?
For C interop your type should also have the exportc pragma. You might also want to add byref or bycopy to the type to enforce one behavior or the other as by default Nim pass by ref if the struct is more than 3 words on the stack (24 bytes on x86-64) and by value otherwise. And lastly you might also want to enforce cdecl, especially for Microsoft MSVC compiler that may use stdcall calling convention.
Example .nim file:
type HugeNum {.exportc: "HugeNum".} = tuple
isNotNeg : bool
num_seq : seq[cuint]
proc fib(a: cint): cint {.exportc.} =
if a <= 2:
result = 1
else:
result = fib(a - 1) + fib(a - 2)
return result
proc example() : seq[cuint] {.exportc.} =
var s : seq[cuint] = @[9'u32]
return s
proc get_seq() : HugeNum {.exportc.} =
var s : HugeNum
s = (isNotNeg : true
, num_seq : @[32'u32 , 12'u32]
)
return s
Header file:
/* Generated by Nim Compiler v1.0.2 */
/* (c) 2017 Andreas Rumpf */
/* The generated code is subject to the original license. */
#ifndef __fib__
#define __fib__
#define NIM_INTBITS 64
#include "nimbase.h"
#undef LANGUAGE_C
...
typedef struct tySequence__U48dCdy0noze9bNL2psZZGA tySequence__U48dCdy0noze9bNL2psZZGA;
typedef struct TGenericSeq TGenericSeq;
typedef struct HugeNum HugeNum;
struct TGenericSeq {
NI len;
NI reserved;
};
struct tySequence__U48dCdy0noze9bNL2psZZGA {
TGenericSeq Sup;
unsigned int data[SEQ_DECL_SIZE];
};
N_NOCONV(void, signalHandler)(int sign);
N_NIMCALL(NI, getRefcount)(void* p);
N_NIMCALL(int, fib)(int a);
N_NIMCALL(tySequence__U48dCdy0noze9bNL2psZZGA*, get_seq2)(void);
N_NIMCALL(void, example)(HugeNum* Result);
N_CDECL(void, NimMain)(void);
#endif /* __fib__ */