调用一个接受来自 Nim 的指向结构的常量指针的 C 函数
Call a C function that accepts a const pointer to struct from Nim
我正在使用 Nim 的 GNU argparse 及其外部函数接口。
在 中有函数 argp_parse 声明如下
extern error_t argp_parse (const struct argp *__restrict __argp,
int __argc, char **__restrict __argv,
unsigned __flags, int *__restrict __arg_index,
void *__restrict __input);
棘手的部分是第一个参数之前的const和__restrict,在Nim中我写了这段代码
type
ArgpChild {.importc: "struct argp_child"} = object
argp : ptr[Argp]
flags : cint
header : cstring
group : cint
Argp* {.importc: "struct argp", header: "<argp.h>"} = object
options : ptr[ArgpOption]
parser : pointer #proc (key : cint, arg: cstring, state : ptr[ArgpState]) : Error
args_doc : cstring
doc : cstring
children : ArgpChild
help_filter : pointer #proc(key : int, text : cstring, input: pointer) : cstring
argp_domain : cstring
ArgpOption* {.importc: "struct argp_option"} = object
name : cstring
key : cint
arg : cstring
flags : cint
doc : cstring
group : cint
ArgpState {.importc: "struct argp_state"} = object
input : pointer
Error* = enum
ARGP_KEY_ARG = 0,
ARGP_ERR_UNKNOWN = 7,
ARGP_KEY_END = 0x1000001
proc argp_parse*(argp : Argp, argc : cint, argv : cstringArray, flags: cuint, arg_index: ptr[cint], input : pointer) : Error {.importc: "argp_parse".}
问题是 Nim 编译器(带有 c 后端)为 argp_parse 函数生成了这一行(注意在第一个参数之前缺少 const 和 __restrict 关键字)
N_CDECL(Error177010, argp_parse)(struct argp* argp0, int argc0, NCSTRING* argv0, unsigned int flags0, int* argindex0, void* input0);
然后,当 gcc 处理那个文件时,它抱怨叫喊 "conflicting types for ‘argp_parse’",我猜这是因为它在第一个参数中找到了两个不同类型的相同函数的定义。
有什么方法可以强制 Nim 编译器在使用 c 后端时在函数参数前添加 const(可能 __restrict)关键字?
Nim 将来会支持 restrict
编译指示,允许您指定此类参数。从 Nim 存储库中的最新 todo.txt 中可以明显看出这一点。
同时,有一种可能的解决方法。您可以使用 emit
pragma:
而不是使用 importc
pragma
proc argp_parse*(argp: Argp,
argc: cint,
argv: cstringArray,
flags: cuint,
arg_index: ptr[cint],
input: pointer): Error =
{.emit: "argp_parse(`argp`, `argc`, `argv`, `flags`, `arg_index`, `input`);".}
这将创建一个常规的非导入过程,它只转发对 argp_parse
函数的调用。
正确的解决方法是简单地添加 header
:
when defined case_bad: # error: conflicting types for 'strlen'
proc c_strlen(a: cstring): csize_t {.importc: "strlen".}
else: # ok
proc c_strlen(a: cstring): csize_t {.importc: "strlen", header: "<string.h>".}
echo c_strlen("abc")
我正在使用 Nim 的 GNU argparse 及其外部函数接口。
在
extern error_t argp_parse (const struct argp *__restrict __argp,
int __argc, char **__restrict __argv,
unsigned __flags, int *__restrict __arg_index,
void *__restrict __input);
棘手的部分是第一个参数之前的const和__restrict,在Nim中我写了这段代码
type
ArgpChild {.importc: "struct argp_child"} = object
argp : ptr[Argp]
flags : cint
header : cstring
group : cint
Argp* {.importc: "struct argp", header: "<argp.h>"} = object
options : ptr[ArgpOption]
parser : pointer #proc (key : cint, arg: cstring, state : ptr[ArgpState]) : Error
args_doc : cstring
doc : cstring
children : ArgpChild
help_filter : pointer #proc(key : int, text : cstring, input: pointer) : cstring
argp_domain : cstring
ArgpOption* {.importc: "struct argp_option"} = object
name : cstring
key : cint
arg : cstring
flags : cint
doc : cstring
group : cint
ArgpState {.importc: "struct argp_state"} = object
input : pointer
Error* = enum
ARGP_KEY_ARG = 0,
ARGP_ERR_UNKNOWN = 7,
ARGP_KEY_END = 0x1000001
proc argp_parse*(argp : Argp, argc : cint, argv : cstringArray, flags: cuint, arg_index: ptr[cint], input : pointer) : Error {.importc: "argp_parse".}
问题是 Nim 编译器(带有 c 后端)为 argp_parse 函数生成了这一行(注意在第一个参数之前缺少 const 和 __restrict 关键字)
N_CDECL(Error177010, argp_parse)(struct argp* argp0, int argc0, NCSTRING* argv0, unsigned int flags0, int* argindex0, void* input0);
然后,当 gcc 处理那个文件时,它抱怨叫喊 "conflicting types for ‘argp_parse’",我猜这是因为它在第一个参数中找到了两个不同类型的相同函数的定义。
有什么方法可以强制 Nim 编译器在使用 c 后端时在函数参数前添加 const(可能 __restrict)关键字?
Nim 将来会支持 restrict
编译指示,允许您指定此类参数。从 Nim 存储库中的最新 todo.txt 中可以明显看出这一点。
同时,有一种可能的解决方法。您可以使用 emit
pragma:
importc
pragma
proc argp_parse*(argp: Argp,
argc: cint,
argv: cstringArray,
flags: cuint,
arg_index: ptr[cint],
input: pointer): Error =
{.emit: "argp_parse(`argp`, `argc`, `argv`, `flags`, `arg_index`, `input`);".}
这将创建一个常规的非导入过程,它只转发对 argp_parse
函数的调用。
正确的解决方法是简单地添加 header
:
when defined case_bad: # error: conflicting types for 'strlen'
proc c_strlen(a: cstring): csize_t {.importc: "strlen".}
else: # ok
proc c_strlen(a: cstring): csize_t {.importc: "strlen", header: "<string.h>".}
echo c_strlen("abc")