2016-07-28 3 views
3

C++로 설계된 PLSQL Developer IDE 용 플러그인으로 사용될 C# DLL을 만들고 있습니다.C# 포인터에 C# 포인터를 할당하는 방법

C# DLL은 C++ 포인터를 받아 들여 나중에 포인터를 함수 또는 메서드에 할당해야 나중에 호출 할 수 있습니다.

IDE는 이러한 플러그인을 작성하기위한 사양 문서를 제공하지만 C++ 및 Delphi 용 샘플 만 제공합니다. 내가 지금까지 가지고

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 번호 : 사양 문서는 내가이 screenshot.

제공 C++ 예에 포함 된 추가 정보를 제공

나는 로버트를 사용하고 있음을 유의 Gieseckes Unmanaged Exports 내보내기 기능을위한 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++ 포인터 인수를 지정할 수 있습니다 ?

+0

C#에서'void *'유형을 사용해 보셨습니까? –

+0

AddP 매개 변수를 intPtr에서 void *로 변경할 수 있습니다. 그렇다면 void * Addr을 메서드에 할당하려면 어떻게해야합니까? 감사. –

+1

'Marshal.GetDelegateForFunctionPointer()' –

답변

2

실용적인 목적으로, 컴파일 된 메소드는 런타임에 변경할 수 없습니다. 따라서 코드 예제에서 IDE_Connected()의 기능을 변경하는 것은 불가능합니다.

그러나 메서드를 delegates (here 참조)으로 선언하고 각각의 정적 인스턴스를 만들 수 있습니다. 나는이 테스트를하지 않은,하지만 대신 char**의, out char[] 또는 더 나은, out string을 사용하는 IDE_GetConnectionInfoIDE_GetBrowserInfo의 방법 서명을 변경해보십시오 :

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

참고 :이보십시오. 이렇게하면 API가 C#에서 더 유용하게됩니다.

+0

모든 도움을 주셔서 다시 한 번 감사드립니다. –