пакетный созданный интерфейс C в nimlang с шаблоном / макросом? - PullRequest
0 голосов
/ 26 января 2019

BackGround

На самом деле я портирую FLTK C 1.3.3 для FreeBASIC на nimlang . Обратите внимание: FLTK C 1.3.3 для FreeBASIC - это интерфейс C на FLTK в CPP .

Многие функции в DLL встречаются с одинаковым форматом имен, например

#inclib "fltk-c-1.3.3-64" ' Windows 64-bit

function Fl_ButtonExNew (byval x as long, byval y as long, byval w as long, byval h as long, byval title as const zstring ptr=0) as Fl_ButtonEx Ptr
sub Fl_ButtonExDelete(byval x as Fl_ButtonEx ptr)

function Fl_BoxExNew (byval x as long, byval y as long, byval w as long, byval h as long, byval title as const zstring ptr=0) as Fl_BoxEx Ptr
sub Fl_BoxExDelete(byval x as Fl_BoxEx ptr)

and so on

и кажется, что функция / подпрограмма delcared автоматически загрузит функцию с тем же именем в fltk-c-1.3.3-64.dll (исправьте меня, если я ошибаюсь)

Решение в FreeBASIC

Итак, в заголовке FreeBASIC fltk-main.bi есть вспомогательный макрос

#macro DeclareEx(_name_)
declare function _name_##ExNew(byval x as long, byval y as long, byval w as long, byval h as long, byval title as const zstring ptr=0) as _name_##Ex ptr
declare sub      _name_##ExDelete         (byref ex as _name_##Ex ptr)
#endmacro

, с помощью которого вышеуказанный код (и многие другие коды) можно сгенерировать с помощью простого однострочного кода:

DeclareEx(Fl_Button)
DeclareEx(Fl_Box)

Мой вопрос по nimlang

В nimlang (пока не обращайте внимания на преобразование типов чисел), вышеприведенный код можно перевести вручную как

const fltk = "fltk-c-1.3.3-64.dll"
type long = int64
proc Fl_ButtonExNew (x: long, y: long, w: long, h: long, title: cstring=nil): Ptr Fl_ButtonEx {.cdecl, importc: "Fl_ButtonExNew", dynlib: fltk, discardable.}
proc Fl_ButtonExDelete(x: ptr Fl_ButtonEx) {.cdecl, importc: "Fl_ButtonExDelete", dynlib: fltk, discardable.}

proc Fl_BoxExNew (x: long, y: long, w: long, h: long, title: cstring=nil): Ptr Fl_BoxEx {.cdecl, importc: "Fl_BoxExNew", dynlib: fltk, discardable.}
proc Fl_BoxExDelete(x: ptr Fl_BoxEx) {.cdecl, importc: "Fl_BoxExDelete", dynlib: fltk, discardable.}

Поэтому я пытаюсь имитировать то, что макрос FreeBASIC делает как

const fltk = "fltk-c-1.3.3-64.dll"
type long = int64

template DeclareEx*(name: untyped) {.dirty.}=
    type `name Ex` = object
    type `name ExNew`* = proc(x: long, y: long, w: long, h: long, title: cstring=nil): ptr `name Ex` {.cdecl, importc: "name New", dynlib: fltk, discardable.}
    type `name ExDelete`*  = proc(ex: ptr `name Ex`) {.cdecl, importc: "name ExDelete", dynlib: fltk, discardable.}

DeclareEx(Fl_Button)

Но когда я скомпилирую, я получаю

d.nim (9, 10) шаблон / универсальный экземпляр DeclareEx отсюда

d.nim (6, 118) Ошибка: неверная прагма: importc: "name New"

Итак, какое-нибудь решение? Спасибо

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Предложенная в шаблонах интерполяция обратных меток может использоваться только в позициях, где ожидаются идентификаторы.Прагма importc ожидает константное строковое выражение.Вы можете использовать магию astToStr для преобразования любого ввода AST в соответствующее ему строковое представление, и это ключ к решению здесь:

const fltk = "fltk-c-1.3.3-64.dll"
type long = int64

template DeclareEx*(name: untyped) =
  const
    newProc = astToStr(name) & "New"
    deleteProc = astToStr(name) & "ExDelete"

  type `name Ex`* {.inject.} = object
  proc `name ExNew`*(x: long, y: long, w: long, h: long, title: cstring=nil): ptr `name Ex` {.cdecl, inject, importc: newProc, dynlib: fltk, discardable.}
  proc `name ExDelete`* (ex: ptr `name Ex`) {.cdecl, inject, importc: deleteProc, dynlib: fltk, discardable.}

DeclareEx(Fl_Button)
DeclareEx(Fl_Window)

var btn: ptr Fl_ButtonEx
Fl_ButtonExDelete(btn)
0 голосов
/ 26 января 2019

Прагма importc используется для импорта процедуры или переменной из C. Однако вы пишете importc: "name New", а name New не является допустимым идентификатором в C, поскольку в нем есть пробел. , Вам нужно будет попытаться объединить символическое имя переменной, которую вы передаете в шаблон, с этим дополнительным строковым суффиксом.

Я не знаю, как вы можете сделать это в шаблоне, хотя. Возможно, вы могли бы передать строку в качестве параметра, а затем использовать оператор &, чтобы объединить ее с суффиксом для importc.

...