Вызвать функцию C, которая принимает константный указатель на структуру из Nim.

Я использую GNU argparse от Nim, используя его внешний функциональный интерфейс. В ‹argp.h› есть функция 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 обрабатывает этот файл, он жалуется, выкрикивая «конфликтующие типы для ‘argp_parse’», я думаю, это потому, что он находит два определения одних и тех же функций с разными типами в первом параметре.

Есть ли способ заставить компилятор Nim добавить ключевое слово const (и, возможно, __restrict) перед параметром функции при использовании бэкэнда c?


person woggioni    schedule 08.01.2017    source источник


Ответы (2)


В будущем Nim будет поддерживать прагму restrict, которая позволит вам указывать такие параметры. Это видно из последнего todo.txt в хранилище Ним.

Между тем, есть один возможный обходной путь для этого. Вместо использования прагмы importc вы можете использовать прагму emit:

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.

person zah    schedule 08.01.2017

Правильное решение — просто добавить 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")
person timotheecour    schedule 29.03.2020