Как назначить указатель C ++ для функции C #

Я создаю C # DLL, которая будет использоваться в качестве плагина для IDE PLSQL Developer, которая разработана на C ++.

Моя C # DLL должна принять указатель C ++, а затем назначить этот указатель на функцию или метод, которые будут вызваны позже.

Среда IDE предоставляет документ спецификации для создания этих плагинов, но предоставляет только примеры для C ++ и Delphi. Документ со спецификациями предоставляет больше информации, которую я включил в этот
Скриншот.

Предоставленный пример C ++:

void (*IDE_MenuState)(int ID, int Index, BOOL Enabled);
BOOL (*IDE_Connected)();
void (*IDE_GetConnectionInfo)(char **Username, char **Password, char **Database);
void (*IDE_GetBrowserInfo)(char **ObjectType, char **ObjectOwner, char **ObjectName);

void RegisterCallback(int Index, void *Addr)
{
switch (Index)
{
case 10 :
(void *)IDE_MenuState = Addr;
break;
case 11 :
(void *)IDE_Connected = Addr;
break;
case 12 :
(void *)IDE_GetConnectionInfo = Addr;
break;
case 13 :
(void *)IDE_GetBrowserInfo = Addr;
break;
}
}

C # у меня так далеко:

Должен отметить, что я использую Роберта Гизекеса Неуправляемый экспорт NuGet Пакет для экспорта функций. Я могу изменить это при необходимости.

public bool IDE_Connected()
{
return false;
}

public void IDE_MenuState(int ID, int Index, bool Enabled)
{

}

[DllExport("add", CallingConvention = CallingConvention.Cdecl, ExportName= "RegisterCallback")]
public static void RegisterCallback(int Index, IntPtr Addr)
{
if (Index == 10)
{
// Assign IntPtr Addr to IDE_MenuState()
// Please help :)
}
if (Index == 11)
{
// Assign IntPtr Addr to IDE_Connected()
// Please help :)
}

}

Как я могу присвоить аргумент указателя C ++ моим методам C #?

3

Решение

В практических целях скомпилированные методы не могут быть изменены во время выполнения. Таким образом, изменение функциональности IDE_Connected() (из вашего примера кода) невозможно.

Однако вы можете объявить ваши методы как delegates (увидеть Вот) и создайте статический экземпляр каждого из них. Попробуй это:

public unsafe class MyClass
{
delegate void IDE_MenuState(int ID, int Index, bool Enabled);
delegate bool IDE_Connected();
delegate void IDE_GetConnectionInfo(char** Username, char** Password, char** Database);
delegate void IDE_GetBrowserInfo(char** ObjectType, char** ObjectOwner, char** ObjectName);

static IDE_MenuState method_IDE_MenuState;
static IDE_Connected method_IDE_Connected;
static IDE_GetConnectionInfo method_IDE_GetConnectionInfo;
static IDE_GetBrowserInfo method_IDE_GetBrowserInfo;

public static void RegisterCallback(int Index, IntPtr Addr)
{
switch (Index)
{
case 10:
method_IDE_MenuState = (IDE_MenuState)Marshal.GetDelegateForFunctionPointer(Addr, typeof(IDE_MenuState));
break;
case 11:
method_IDE_Connected = (IDE_Connected)Marshal.GetDelegateForFunctionPointer(Addr, typeof(IDE_Connected));
break;
case 12:
method_IDE_GetConnectionInfo = (IDE_GetConnectionInfo)Marshal.GetDelegateForFunctionPointer(Addr, typeof(IDE_GetConnectionInfo));
break;
case 13:
method_IDE_GetBrowserInfo = (IDE_GetBrowserInfo)Marshal.GetDelegateForFunctionPointer(Addr, typeof(IDE_GetBrowserInfo));
break;
}
}

public static void IDE_MenuState(int ID, int Index, bool Enabled)
{
if (method_IDE_MenuState == null)
{
throw new MissingMethodException("IDE_MenuState has not been assigned pointer yet.");
}
method_IDE_MenuState(ID, Index, Enabled);
}

public static bool IDE_Connected()
{
if (method_IDE_Connected == null)
{
throw new MissingMethodException("IDE_Connected has not been assigned pointer yet.");
}
return method_IDE_Connected();
}

public static void IDE_GetConnectionInfo(char** Username, char** Password, char** Database)
{
if (method_IDE_GetConnectionInfo == null)
{
throw new MissingMethodException("IDE_GetConnectionInfo has not been assigned pointer yet.");
}
method_IDE_GetConnectionInfo(Username, Password, Database);
}

public static void IDE_GetBrowserInfo(char** ObjectType, char** ObjectOwner, char** ObjectName)
{
if (method_IDE_GetBrowserInfo == null)
{
throw new MissingMethodException("IDE_GetBrowserInfo has not been assigned pointer yet.");
}
method_IDE_GetBrowserInfo(ObjectType, ObjectOwner, ObjectName);
}
}

Примечание: я не проверял это, но попробуйте изменить сигнатуры метода IDE_GetConnectionInfo а также IDE_GetBrowserInfo использовать out char[] или даже лучше, out string, вместо char**, Это сделает ваш API более полезным в C #.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]