2016-07-28 9 views
3

Ich erstelle eine C# -DLL, die als Plug-In für die PLSQL Developer IDE verwendet wird, die in C++ entwickelt wurde.So weisen Sie einer C# -Funktion einen C++ - Zeiger zu

Meine C# -DLL muss einen C++ - Zeiger akzeptieren und diesen Zeiger dann einer Funktion oder Methode zuweisen, die später aufgerufen wird.

Die IDE stellt ein Spezifikationsdokument zum Erstellen dieser Plug-ins bereit, stellt jedoch nur Beispiele für C++ und Delphi bereit. Die Spezifikationen Dokument enthält weitere Informationen, die ich in diesem screenshot. enthalten

bereitgestellt C++ Beispiel:

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# ich bisher habe:

Ich sollte anmerken, dass ich Robert bin mit Gieseckes Unmanaged Exports NuGet Paket zum Export von Funktionen. Ich kann das ändern, wenn nötig.

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 :) 
    } 

} 

Wie kann ich den C++ Zeiger Argument meiner C# Methoden zuweisen?

+0

Haben Sie den 'void *' Typ in C# versucht? –

+0

Ich könnte den Addr-Parameter von intPtr zu void * ändern. Was würde ich tun, um void * Addr einer Methode zuzuweisen? Vielen Dank. –

+1

Sie könnten versuchen, Marshal.GetDelegateForFunctionPointer() ' –

Antwort

2

Aus praktischen Gründen können kompilierte Methoden zur Laufzeit nicht geändert werden. Eine Änderung der Funktionalität von IDE_Connected() (aus Ihrem Codebeispiel) ist nicht möglich.

Sie können jedoch Ihre Methoden als delegates deklarieren (siehe here) und eine statische Instanz erstellen. Versuchen Sie folgendes:

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); 
    } 
} 

Hinweis: Ich kann das nicht getestet haben, sondern versuchen, die Methodensignaturen von IDE_GetConnectionInfo ändern und IDE_GetBrowserInfoout char[] zu verwenden, oder noch besser, out string, statt char**. Dadurch wird Ihre API in C# nützlicher.

+0

Nochmals vielen Dank für Ihre Hilfe. –

Verwandte Themen