2013-11-21 19 views
1

我正在使用由.dll,.lib和.h文件组成的3. party SDK。我正在使用.dll来对付PInvoke。和.h文件来查看函数名称和参数。 (所以我没有使用.lib文件)。用于2 **指针的C#PInvoke

SDK相当复杂,所以使得PInvoke包装被证明是一个挑战。所有的函数/结构体/枚举都在.h文件中定义。

我的问题是如何实现与2 **功能pinvoke。

我希望这是我的C#函数定义是错误的。 当我调用函数时,它简单地崩溃,没有异常抛出或任何东西。该程序停止。

功能:GetInformatiuon(...)

//C Function: GetInformatiuon(...) 
ERROR GetInformatiuon(
    Component comp, 
    struct Information** Info); 

//C# Function: GetInformatiuon(...) 
[DllImport("externalSDK.dll", EntryPoint = "GetInformatiuon", CallingConvention = CallingConvention.Cdecl)] 
    public static extern ERROR GetInformatiuon(Component comp, ref Information Info); 
); 

枚举:错误

//C Enum: ERROR 
typedef enum ERROR_E { 
    OK = 0, //Everything is ok 
    E_ARG = 1, //Error in the Arguments 
    E_DATA = 2 //Data error 
    //And more... 
} ERROR; 

//C# Enum: ERROR 
public enum ERROR 
{ 
    OK = 0, //Everything is ok 
    E_ARG = 1, //Error in the Arguments 
    E_DATA = 2 //Data error 
    //And more... 
} 

结构:组件

//C struct: Component 
typedef struct Component_S 
{ 
    void* ObjPointer;  
    unsigned long number; 
} Component; 

//C# class: Component 
[StructLayout(LayoutKind.Sequential)] 
public class Component 
{ 
    public IntPtr ObjPointer; 
    public uint number; //uint because usigned long C is 4 bytes (32 bits) and C# ulong is 8 bytes (64 bits), where C# uint is 4 bytes(32 bits) 
} 

的结构:信息

//C struct: Information 
typedef struct Information_S { 
    char* language;   
    unsigned long sampleFrequency; 
    unsigned long frameShift;  
}Information; 

//C# struct: Information 
[StructLayout(LayoutKind.Sequential)] 
public struct Information 
{ 
    public string language; 
    public uint sampleFrequency; //uint because usigned long C is 4 bytes (32 bits) and C# ulong is 8 bytes (64 bits), where C# uint is 4 bytes(32 bits) 
    public uint frameShift;  //uint because usigned long C is 4 bytes (32 bits) and C# ulong is 8 bytes (64 bits), where C# uint is 4 bytes(32 bits) 
} 
+3

你”必须声明它为'out IntPtr'。然后使用Marshal.PtrToStructure()来转换它。然后烦恼很多,关于如何获得分配给结构再次释放的内存。这是一个糟糕的签名,如果可以的话,更改C代码。 –

+0

正如汉斯上面所说,签名中的struct Information **意味着你指向* another *指针的内存中的位置,并且你的C#extern函数调用不会处理实际的信息结构,除非你做了一些编组 – nvuono

+0

可悲的是我不能改变C签名。但我会尝试Hans提到的“out IntPtr”解决方案 –

回答

1

我找到了解决办法! (又名汉斯帕桑特评论)

我改变了功能:

功能:GetInformatiuon(...)

//C Function: GetInformatiuon(...) 
ERROR GetInformatiuon(
    Component comp, 
    struct Information** Info); 

//C# Function: GetInformatiuon(...) 
[DllImport("externalSDK.dll", EntryPoint = "GetInformatiuon", CallingConvention = CallingConvention.Cdecl)] 
    public static extern ERROR GetInformatiuon(Component comp, out IntPtr InfoPtr); 
); 

调用函数

IntPtr infoPtr; 
lhErr = SDK.GetInformatiuon(component, out infoPtr); 
Information info = (Information)Marshal.PtrToStructure(infoPtr, typeof(Information)) ;