[英]C# Calling C++ DLL Function which returns a struct
I have an C++ dll which defines a struct and an dll call like this:我有一个 C++ dll,它定义了一个结构体和一个 dll 调用,如下所示:
typedef const char* FString;
typedef struct {
FString version;
FString build_no;
FString build_type;
FString build_date;
FString build_info;
FString comment;
} FVersionInfo;
extern "C" FAPI_EXPORT FVersionInfo CALLINGCONV fGetVersion(void);
On the c# side i using an dynamic loading:在 C# 方面,我使用动态加载:
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
static extern int LoadLibrary(
[MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
static extern IntPtr GetProcAddress(int hModule,
[MarshalAs(UnmanagedType.LPStr)] string lpProcName);
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
static extern bool FreeLibrary(int hModule);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct FVersionInfo
{
public string Version;
public string Build_No;
public string Build_Type;
public string Build_Date;
public string Build_Info;
public string Comment;
}
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public delegate FVersionInfo fGetVersion();
public fGetVersion GetVersion;
FHandle = LoadLibrary(@pName);
IntPtr intPtr;
intPtr = GetProcAddress(FHandle, "fGetVersion");
GetVersion = (fGetVersion)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(fGetVersion));
The calling code should be:调用代码应该是:
FVersionInfo version = new FVersionInfo();
version = GetVersion();
My first problem is, that i become an "System.Runtime.InteropServices.MarshalDirectiveException" on the call of Marshal.GetDelegateForFunctionPointer in the c# loading part.我的第一个问题是,我在 c# 加载部分调用 Marshal.GetDelegateForFunctionPointer 时变成了“System.Runtime.InteropServices.MarshalDirectiveException”。
I have then tested using IntPtr as struct return parameter like that:然后我使用 IntPtr 作为结构返回参数进行了测试,如下所示:
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public delegate IntPtr fGetVersion();
So i got the Marshal.GetDelegateForFunctionPointer to work, but later i've got the same problems with marshaling:所以我让 Marshal.GetDelegateForFunctionPointer 工作,但后来我在编组方面遇到了同样的问题:
IntPtr DllValue = new IntPtr();
FVersionInfo version = new FVersionInfo();
DllValue = fGetVersion();
Marshal.PtrToStructure(DllValue, FVersionInfo);
Here it crashes at the fGetVersion() call with "Managed Debugging Assistant 'PInvokeStackImbalance'".在这里,它在 fGetVersion() 调用时崩溃,带有“托管调试助手‘PInvokeStackImbalance’”。 I think it means, that the stack is corrupted (imbalanced).我认为这意味着堆栈已损坏(不平衡)。
I have tested with many variants of the structure definition, but no result.我已经用结构定义的许多变体进行了测试,但没有结果。
Any ideas or suggestions would be welcome!欢迎任何想法或建议!
Thanks for the direction, but i found an working solution:感谢您的指导,但我找到了一个可行的解决方案:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct FVersionInfo { public IntPtr Version; public IntPtr Build_No; public IntPtr Build_Type; public IntPtr Build_Date; public IntPtr Build_Info; public IntPtr Comment; }
So i passed the Marshal.GetDelegateForFunctionPointer
without any problems.所以我通过Marshal.GetDelegateForFunctionPointer
没有任何问题。
I changed my using code to:我将使用代码更改为:
GF.FVersionInfo vi = new GF.FVersionInfo(); vi = gf.GetVersion();
string MyVersion = Marshal.PtrToStringAnsi(VersionInfos.Version); string MyVersion = Marshal.PtrToStringAnsi(VersionInfos.Version);
An example when using a struct with const char * members.使用具有 const char * 成员的结构的示例。 This can be a scenario where you have your own C++ DLL structure to pass back and forth.在这种情况下,您可以使用自己的 C++ DLL 结构来回传递。
// CPP Source code
// ----------------------------------
// Struct definition
struct MyStruct_t {
const char * sStr;
size_t iInt;
};
// ----------------------------------
// C# Source code
// ----------------------------------
// Struct definition
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct MyStruct_t {
public string sStr;
public int iInt;
};
// DLL prototype
[DllImport("Cpp.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void MyFunctionCall(IntPtr MyStruct_t);
// Prepare a struct pointer to pass to DLL
MyStruct_t pMyStruct_t = new MyStruct_t();
IntPtr pMyStructPTR = Marshal.AllocHGlobal(Marshal.SizeOf(pMyStruct_t));
Marshal.StructureToPtr(pMyStruct_t, pMyStructPTR, false);
// Call C++ DLL
MyFunctionCall(pMyStructPTR);
// The DLL updated struct, get the struct
MyStruct_t pMyStruct = (MyStruct_t)Marshal.PtrToStructure(pMyStructPTR, typeof(MyStruct_t));
// Show data
MessageBox.Show(pMyStruct.sStr);
// clean up
if (pMyStructPTR != IntPtr.Zero) { Marshal.FreeHGlobal(pMyStructPTR); pMyStructPTR = IntPtr.Zero; }
// ----------------------------------
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.