Я очень новичок в SWIG и не имею большого опыта работы на C++ в целом. У меня возникли проблемы с пониманием того, как сгенерировать программу на C#, которая может вызывать в C++ dll с помощью SWIG. Я просмотрел множество примеров и сообщений на форуме, но все это, кажется, вне меня. Пожалуйста, может кто-нибудь объяснить мне, что нужно, и что я делаю неправильно в простой форме?Создание оболочки SWIG для указателей функций C++ в C#
У меня есть dll C++ с файлами заголовков, содержащие только определения указателя функции typedef, и я знаю имена экспортируемых функций.
, например
/* example.h */
typedef int (*pointer_add) (const long date, const long noDays, long& result);
Я просто хочу, чтобы иметь простой вызов метода возможно в C# я бы это сделать:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int pointer_add(long date, long noDays, ref long po_res);
public pointer_add addDays { get; protected set; }
// get delegate for function pointer
IntPtr p = NativeMethods.GetProcAddress(libraryHandle, "functionName");
Delegate function = Marshal.GetDelegateForFunctionPointer(p,typeof(pointer_add));
addDays = (pointer_add)function;
// invoke delegate
addDays(date, noDays, out date);
, но мне нужно идти об этом в динамике так SWIG - это инструмент выбора, хотя я не понимаю, как все это должно сочетаться ...
/* interface.i */
%module wrapper
%{
#include "example.h"
%}
%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
%cs_callback(pointer_addDays, AddDays)
// int AddDays(pointer_addDays c);
%include "example.h"
// swig -csharp -c++ interface.i
Я ожидаю, что все волшебство будет найдено в полученном файле interface_wrap.cxx? Когда строка AddDays прокомментирована из файла interface.i, я не могу найти ничего, что связано с AddDays. Если я раскомментировать int AddDays(pointer_addDays c);
(который не найден в исходном файле .h), то я могу видеть, генерируемый в файле:
SWIGEXPORT int SWIGSTDCALL CSharp_addDays(void* jarg1) {
int jresult ;
pointer_addDays arg1 ;
int result;
arg1 = (pointer_addDays)jarg1;
result = (int)addDays(arg1); // compiler error - identifier "addDays" is undefined!
jresult = result;
return jresult;
}
, а также я могу видеть добавил в файле wrapperPINVOKE.cs:
[global::System.Runtime.InteropServices.DllImport("wrapper", EntryPoint="CSharp_addDays")]
public static extern int addDays(AddDays jarg1);
Я вообще по правому краю? Пожалуйста, кто-нибудь может сообщить, что я делаю неправильно, чтобы получить ошибки в файле wrap.cxx и каковы следующие шаги?
Ваш пример.h имеет только typedef, но для вашего интерфейса SWIG это то, как вы хотите, чтобы вещи такого типа пересекали границу языка, которая имеет значение. У вас просто есть глобальная переменная в вашем C++, или это аргумент, который также передается в функции?Вы просто реализуете его на C++ или вам нужно передать код C#? – Flexo
@Flexo У меня нет доступа к источнику C++, только заголовкам. Я не уверен, что вы подразумеваете, имея глобальную переменную в C++, но из того, что я вижу, typedefs не передаются в качестве аргумента. Функции выполняются в источнике C++, это то, что я пытаюсь вызвать, мне не нужно передавать какой-либо код на C#. В некоторых случаях один вызов функции возвращал объект, и мне нужно было бы передать эту ссылку в другую функцию. Наверное, это то, к чему предназначена карта сайта «IntPtr», чтобы справиться с этим на стороне C#? – SWilliams
Если они реализованы на C++, и все, что вы хотите сделать, это позвонить им, то как вы их найдете, чтобы называть их? – Flexo