如何将 C++ 结构传递给 C# DLL?
How to pass C++ Struct To C# DLL?
我在下面有一个 C# DLL。我想在 C++ Builder 中使用这个 C# DLL。
但我不知道 C# Struct 和 C++ Struct 编组:
using RGiesecke.DllExport;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace TestLibrary
{
[ComVisible(true)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyStruct
{
public int X;
public int Y;
}
public class Class1
{
[DllExport("DoSomething", CallingConvention = CallingConvention.StdCall)]
public static int DoSomething(int x, int y, ref MyStruct myStruct)
{
myStruct.X = 50;
myStruct.Y = 75;
return x + y;
}
}
}
我想从下面的 C++ Builder 传递 "myStruct" 参数。
void __fastcall TForm1::FormCreate(TObject *Sender)
{
struct MyStruct
{
int X;
int Y;
};
int (__stdcall *DoSomething)(int,int,MyStruct);
HINSTANCE dllHandle = NULL;
dllHandle = LoadLibrary( edtdllPath->Text.c_str());
if(dllHandle == NULL) return;
int status = -1;
try
{
DoSomething =(int (__stdcall *)(int,int,MyStruct)) GetProcAddress(dllHandle, "DoSomething");
}
catch(Exception &Err)
{
ShowMessage(Err.Message);
}
if(DoSomething != NULL)
{
try
{
MyStruct myStruct;
status = DoSomething(5,5,myStruct);
String strStatus = status;
ShowMessage(strStatus);
ShowMessage(myStruct.X);
ShowMessage(myStruct.Y);
}
catch(EAccessViolation &err)
{
ShowMessage(err.Message);
}
}
}
当我调试代码时,myStruct.X 和 myStruct.Y 值是错误的。
我哪里错了?
您没有将您的结构作为指针传递给 c#,但在 c# 中您告诉它是一个指针 (ref
)。
C# 项目这样声明结构参数:
ref MyStruct myStruct
作为指向结构的指针进行编组。在 C++ 中,这意味着
MyStruct*
所以把函数指针变量的声明改成这样:
int (__stdcall *DoSomething)(int,int,MyStruct*);
并在施放时使用相同的类型:
DoSomething =(int (__stdcall *)(int,int,MyStruct*)) GetProcAddress(dllHandle, "DoSomething");
请注意,typedef 在这里会更好地为您服务,以避免重复您自己。还要注意 GetProcAddress
不会引发异常。它通过返回 NULL
来表示错误。您没有正确检查错误。
调用函数时传递结构地址:
status = DoSomething(5,5,&myStruct);
声明 status
并将其初始化为 -1 也有点毫无意义,但稍后会覆盖该值。像这样声明和初始化它会更惯用:
int status = DoSomething(5,5,&myStruct);
我在下面有一个 C# DLL。我想在 C++ Builder 中使用这个 C# DLL。
但我不知道 C# Struct 和 C++ Struct 编组:
using RGiesecke.DllExport;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace TestLibrary
{
[ComVisible(true)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyStruct
{
public int X;
public int Y;
}
public class Class1
{
[DllExport("DoSomething", CallingConvention = CallingConvention.StdCall)]
public static int DoSomething(int x, int y, ref MyStruct myStruct)
{
myStruct.X = 50;
myStruct.Y = 75;
return x + y;
}
}
}
我想从下面的 C++ Builder 传递 "myStruct" 参数。
void __fastcall TForm1::FormCreate(TObject *Sender)
{
struct MyStruct
{
int X;
int Y;
};
int (__stdcall *DoSomething)(int,int,MyStruct);
HINSTANCE dllHandle = NULL;
dllHandle = LoadLibrary( edtdllPath->Text.c_str());
if(dllHandle == NULL) return;
int status = -1;
try
{
DoSomething =(int (__stdcall *)(int,int,MyStruct)) GetProcAddress(dllHandle, "DoSomething");
}
catch(Exception &Err)
{
ShowMessage(Err.Message);
}
if(DoSomething != NULL)
{
try
{
MyStruct myStruct;
status = DoSomething(5,5,myStruct);
String strStatus = status;
ShowMessage(strStatus);
ShowMessage(myStruct.X);
ShowMessage(myStruct.Y);
}
catch(EAccessViolation &err)
{
ShowMessage(err.Message);
}
}
}
当我调试代码时,myStruct.X 和 myStruct.Y 值是错误的。
我哪里错了?
您没有将您的结构作为指针传递给 c#,但在 c# 中您告诉它是一个指针 (ref
)。
C# 项目这样声明结构参数:
ref MyStruct myStruct
作为指向结构的指针进行编组。在 C++ 中,这意味着
MyStruct*
所以把函数指针变量的声明改成这样:
int (__stdcall *DoSomething)(int,int,MyStruct*);
并在施放时使用相同的类型:
DoSomething =(int (__stdcall *)(int,int,MyStruct*)) GetProcAddress(dllHandle, "DoSomething");
请注意,typedef 在这里会更好地为您服务,以避免重复您自己。还要注意 GetProcAddress
不会引发异常。它通过返回 NULL
来表示错误。您没有正确检查错误。
调用函数时传递结构地址:
status = DoSomething(5,5,&myStruct);
声明 status
并将其初始化为 -1 也有点毫无意义,但稍后会覆盖该值。像这样声明和初始化它会更惯用:
int status = DoSomething(5,5,&myStruct);