Оболочка C ++ / CLI для C dll - PullRequest
0 голосов
/ 17 июня 2011

Итак, у меня есть исходный код C .dll, который я хочу использовать в своем приложении C #.Вместо того чтобы делать кучу DllImports, я решил написать оболочку для него на C ++ / CLI.

Моя функция C получает указатель на структуру с 4 функциями обратного вызова:

typedef struct
{
 PFN_IN readFp;
 PFN_OUT writeFp;
}OPEN_ARGS;

C ++ / CLI использует один и тот же файл .h, поэтому использует тот же typedef.

Код C # имеет собственное определение этой структуры и делегирует CB, потому что я не могу присоединить .h к проекту C #.

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 PFN_OUT(IntPtr arg, IntPtr pSrc, Int32 len);

    [StructLayout(LayoutKind.Sequential)]
    public struct OPEN_ARGS
    {
        public PFN_IN readFp;
        public PFN_OUT writeFp;
    };

Итак, когда я явно добавляю свою библиотеку C ++ / CLI в ссылки на проекты C #, компилятор не будет принимать вызовы функций C ++ / CLI, говоря:

"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'"

Но если явключите dll C ++ / CLI неявно, как это

[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "?CLIOpen@@YAHHUOPEN_ARGS@@@Z")]
public static extern int CLIOpen(int a, OPEN_ARGS args);

Это будет работать просто отлично.

Так есть ли способ сказать компилятору C # игнорировать эту ошибку приведения типа или может быть другой способ обернуть функции кода C?

EDIT: очищены имена переменных для лучшей читабельности

Ответы [ 3 ]

4 голосов
/ 17 июня 2011

Что делать, если вы сделали это по-другому.Поскольку у вас есть C ++ / CLI DLL, обрабатывающая обязанности взаимодействия между C DLL и сборкой C #, вы можете предоставить эквивалентный API, только используя больше .NET-подобных концепций.

Например, вместо предоставления структурыс помощью указателей на функции вы можете выставить класс с тремя событиями.Сборка C # добавит обработчики для этих событий.Внутри C ++ DLL будут использоваться указатели функций, ожидаемые C DLL, но их реализация будет запускать события .NET, которые обрабатывает сборка C #.

Это обеспечит гораздо лучший опыт использования DLL наC #, и, вероятно, избавиться от ошибок компилятора взаимодействия, с которыми вы сталкиваетесь.

0 голосов
/ 17 июня 2011

Так что для управляемого C ++ вы можете использовать директивы компилятора #pragma managed / unmanaged вместо pInvoke, который, похоже, вы используете. Затем вы можете скомпилировать управляемый и собственный код вместе в одну сборку, даже в один и тот же файл CPP.

Тогда вы можете сделать что-то вроде:

#pragma managed
// include your native headers here
#include "foo.h" // whatever you call it.

#using <System.dll> // what ever else you need here...

// Have to wrap a function in a class, since .NET doesn't allow free standing functions.
public ref class foo
{
public static int sarCLIOpen(int a, SARWrapperTest::Program::SAR_OPEN_ARGS args)
{
// do something to convert your managed args to native args. 
::SAR_OPEN_ARGS native_args = ...
// then call your native function
return sarCLIOpen(a, native_args );
}

};
0 голосов
/ 17 июня 2011

Пожалуйста, рассмотрите возможность использования SWIG для генерации кода-обертки для всего вашего пинвока.

http://www.swig.org/Doc1.3/CSharp.html

...