2015-02-17 2 views
1

Я очень новичок в 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 и каковы следующие шаги?

+0

Ваш пример.h имеет только typedef, но для вашего интерфейса SWIG это то, как вы хотите, чтобы вещи такого типа пересекали границу языка, которая имеет значение. У вас просто есть глобальная переменная в вашем C++, или это аргумент, который также передается в функции?Вы просто реализуете его на C++ или вам нужно передать код C#? – Flexo

+0

@Flexo У меня нет доступа к источнику C++, только заголовкам. Я не уверен, что вы подразумеваете, имея глобальную переменную в C++, но из того, что я вижу, typedefs не передаются в качестве аргумента. Функции выполняются в источнике C++, это то, что я пытаюсь вызвать, мне не нужно передавать какой-либо код на C#. В некоторых случаях один вызов функции возвращал объект, и мне нужно было бы передать эту ссылку в другую функцию. Наверное, это то, к чему предназначена карта сайта «IntPtr», чтобы справиться с этим на стороне C#? – SWilliams

+0

Если они реализованы на C++, и все, что вы хотите сделать, это позвонить им, то как вы их найдете, чтобы называть их? – Flexo

ответ

1

После некоторых проб и ошибок, я думаю, мне удалось получить эту работу.

Код/typemaps с %define %cs_callback(TYPE, CSTYPE) не были необходимы, чтобы просто вызвать функции, к которым я пытался добраться. Функции не были включены в файлы .h, но поскольку я знал их соглашение об именах, я мог бы добавить их сам.

Для всех определений типов, которые я имел, я изменил их в подпись функции в интерфейсе .i файл:

%module test 
%{ 
#include "example.h" 
%} 

// all typedefs converted to functions by convention e.g. 
int addDays(const long date, const long noDays, long& result); 

Поскольку эти функции не были включены в заголовках (которые должны быть добавлены к полученному C++/CLI обертка проекта), я также должен был сделать свой заголовочный файл exportedFunctions.h

// exportedFunctions.h 
namespace NamespaceUsedInCPlusPlusCode 
{ 
extern "C" __declspec(dllexport) int addDays(const long date, const long noDays, long& result); 
} 

и включить это в SWIG сгенерированный .cpp файл так, чтобы он мог найти функции и компилировать.

// interface_wrap.cxx 
#include "exportedFunctions.h" 

Это означает, что функция addDays была как обернута SWIG и нашла в сгенерированном коде .cxx, и позвольте мне скомпилировать SWIG сгенерированного кода.

Смежные вопросы