看看下面的代码,我用它来调用c(而不是C++)dll。我知道这不是对你的问题的真正回答,但也许你可以使用其中的一些事情。
请注意dll声明中的“CallingConvention”指示符以及try catch的“finally”部分中的“FreeGlobal”。
public class csInterface
{
[DllImport(@"myDLL.dll", EntryPoint = "dllFunc", CallingConvention = CallingConvention.StdCall)]
private static extern void dllFunc(IntPtr inp, IntPtr outp);
public static int myDll(ref MyInput myInput, ref MyOutput myOutput)
{
int sizeIn, sizeOut;
IntPtr ptr_i = IntPtr.Zero, ptr_u = IntPtr.Zero;
sizeIn = Marshal.SizeOf(typeof(myInput));
sizeOut = Marshal.SizeOf(typeof(myOutput));
/* Calling C */
try
{
ptr_i = Marshal.AllocHGlobal(sizeIn);
ptr_u = Marshal.AllocHGlobal(sizeOut);
Marshal.StructureToPtr(myInput, ptr_i, true);
Marshal.StructureToPtr(myOutput, ptr_u, true);
dllFunc(ptr_i, ptr_u);
myOutput = (MyOutput)(Marshal.PtrToStructure(ptr_u, typeof(MyOutput)));
}
catch (Exception)
{
//Return something meaningful (or not)
return -999;
}
finally
{
//Free memory
Marshal.FreeHGlobal(ptr_i);
Marshal.FreeHGlobal(ptr_u);
}
//Return something to indicate it all went well
return 0;
}
}
在C#中,我宣布我的类型
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MySubType
{
public int a;
public double b;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyInput
{
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 4)]
public string aString; //A string of length 3
public bool aBoolean;
public int anInt;
public char aChar;
public double aDouble;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 12)]
public MySubType[] aSubType; //Array of struct of length 12
}
以及输出类似的东西。
用C
现在(它可能是相同的或C++相似),我宣布我的DLL
__declspec(dllexport) void _stdcall dllFunc(MyCInput *myCInput, MyCOutput *myCOutput)
{
//Code
}
和相应的C类型这显然具有镜像C#类型完全相同
typedef struct
{
int a;
double b;
} MyCSubType;
typedef struct
{
char aString[4];
int aBoolean; //This needs to be cast over to your C boolean type
int anInt;
char aChar;
double aDouble;
MyCSubType myCSubType[12];
} MyCType;
现在我在这个例子中使用的类型并不完全符合我在代码中使用的类型,并且我没有测试过这些代码。所以可能会有拼写错误等,但“原则”是可以的。
是否有你决定使用参数作为'IntPtr'而不是'int'作为返回值的原因? – nvoigt
@nvoigt试验,试图让它表现。我已经用int来测试它的两端,IntPtr在两端和其中的一个,如图所示。我很高兴地承认,我对此深表遗憾,只是在绝望中尝试一些事情。 –
你需要找出当C++库被编译时int的大小。然后你需要在C#中选择正确的东西。 “IntPtr”可以是32位或64位,具体取决于您执行代码的位置。您的C++库不能确定在运行时为C#,它将在编译时被修复。 – nvoigt