обертывание интерфейса в стиле C аргументом указателя на функцию в C# - PullRequest
0 голосов
/ 20 февраля 2020

Я начал использовать swig несколько месяцев go, и после нескольких взлетов у меня появилась первая работающая оболочка c#. Теперь мне нужно создать оболочку в C#, которая обертывает интерфейс C, который принимает аргумент функции ptr. Я использовал typedef для функции ptr type и макрос swig cs_callback, который я нашел при исследовании того, как это сделать. Этот макрос необходим, чтобы swig мог сгенерировать полезный тип функции ptr (и имя). В противном случае swig создаст класс SWIGTYPE_p_f_p_InfoBarData__void, который сделает вещи ужасными и сложными.

К сожалению, я, кажется, застрял сейчас. AFAIK Должна происходить одна из двух вещей, которых нет.

1) делегат, соответствующий моему typedef для моей функции ptr, нигде не генерируется

typedef void (_stdcall uiDataObserverFun c) (uiData );

2) Если я попытаюсь использовать карту типов для вставки члена делегата в сгенерированный класс, ничего не произойдет.

Мне кажется, что выход моей глубины здесь и надежды, кто-то может дать мне некоторое представление о том, что происходит не так. Я приложил минимальный пример, который воспроизводимо вызывает у меня головную боль и необходимый файл проекта swig. В моей среде разработки я использую swig 4.0.1.

UiData.h

#pragma once

extern "C" {

struct UiData 
{
    double temperature;
};

}

UiDataProvider

#pragma once

#include "UiData.h"

typedef void (_stdcall *uiDataObserverFunc)(InfoBarData*);


#ifdef UI_EXPORTS
#define UI_API __declspec(dllexport)
#else
#define UI_API __declspec(dllimport)
#endif


extern "C" {

    UI_API void UI_Init();

    UI_API void UI_RegisterObserver(uiDataObserverFunc callbackFunc);
}

UiModule_cs.i

#define UI_EXPORTS

%module UiWrapper

// TYPE: name of the C function ptr typedef
// CSTYPE: name of the corrseponding delegate
%define %cs_callback(TYPE, CSTYPE)
    %typemap(ctype) TYPE, TYPE& "void*"
    %typemap(in) TYPE  %{ $1 = ($1_type)$input; %}
    %typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
    %typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
    %typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
    %typemap(csin) TYPE, TYPE& "$csinput"
%enddef


%rename("%(strip:[UI_])s") "";

%cs_callback(uiDataObserverFunc, cppUiDataObserverCallback)

%typemap(cscode) UiWrapper %{
    [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
    public delegate void cppUiDataObserverCallback(UiData* uiDataUpdate);
%}

%{
#include "UiData.h"
#include "UiDataProvider.h"
%}

// these headers have to come before anything else - otherwise syntax error(1) will be thrown   
%include <windows.i>
%include <carrays.i>
%include <cpointer.i>

%include "UiData.h"
%include "UiDataProvider.h"
call "%swig%\swig.exe" -v -debug-typedef -c++ -csharp -o .\UiWrapper.cpp -outdir .\UiModuleSwig UiModule_cs.i

Я пытался

  • , используя -E, чтобы увидеть, появляется ли что-то подозрительное после предварительной обработки, но но безрезультатно.
  • переупорядочение блоков инструкций swig. Если что-то и происходило, то это ухудшалось.
  • не использовал typedef для делегата (при условии, что я мог неправильно изменить поведение swig) -> без эффекта

С наилучшими пожеланиями и спасибо за ваше время, Фред

...