如何通过C++;结构到C#DLL?
我下面有一个类似的C#DLL。我想在C++ Builder中使用这个C语言DLL。如何通过C++;结构到C#DLL?,c#,c++,struct,pinvoke,marshalling,C#,C++,Struct,Pinvoke,Marshalling,我下面有一个类似的C#DLL。我想在C++ Builder中使用这个C语言DLL。 但是我不知道C结构和C++结构编组: using RGiesecke.DllExport; using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; namespace TestLibrary { [ComVisible(true)] [Str
但是我不知道C结构和C++结构编组:
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下面传递“MyStult”参数,如
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的指针传递,但在c中,您告诉它将是一个指针(ref
)。c项目声明结构参数如下:
ref MyStruct myStruct
int status = DoSomething(5,5,&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,但随后覆盖该值也有点毫无意义。更惯用的做法是这样声明和初始化它:
ref MyStruct myStruct
int status = DoSomething(5,5,&myStruct);
C#项目声明struct参数如下:
ref MyStruct myStruct
int status = DoSomething(5,5,&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,但随后覆盖该值也有点毫无意义。更惯用的做法是这样声明和初始化它:
ref MyStruct myStruct
int status = DoSomething(5,5,&myStruct);
绳子是个大问题。您不能使用
ref-StringBuilder
,我认为您也不能使用StringBuilder
。到目前为止,最简单的解决方案是使用UnmanagedType.BStr
和COMBStr
。你确实需要做一点备份,并且比目前更了解基础知识。谢谢大家的关注@DavidHeffernan。我已经检查了StringBuilder参数,它正在工作。不起作用只有myStruct参数。不,字符串生成器不能起作用。问问自己,谁将释放内存?首先。还有更多的问题。你弄错了。谢谢@DavidHeffernan-ur-guruI,你给X添加了这样的地址。结构MyStruct{int*X;double*Y;};我得到的“myStruct.X”值如下所示。ShowMessage(*myStruct.X);但是*myStruct.X的值是错误的。字符串是一个大问题。您不能使用ref-StringBuilder
,我认为您也不能使用StringBuilder
。到目前为止,最简单的解决方案是使用UnmanagedType.BStr
和COMBStr
。你确实需要做一点备份,并且比目前更了解基础知识。谢谢大家的关注@DavidHeffernan。我已经检查了StringBuilder参数,它正在工作。不起作用只有myStruct参数。不,字符串生成器不能起作用。问问自己,谁将释放内存?首先。还有更多的问题。你弄错了。谢谢@DavidHeffernan-ur-guruI,你给X添加了这样的地址。结构MyStruct{int*X;double*Y;};我得到的“myStruct.X”值如下所示。ShowMessage(*myStruct.X);但是*myStruct.X的值是错误的。我得到的错误是行状态=DoSomething(5,5,&myStruct);[C++错误]Unit1.cpp(63):E2034无法将“MyStruct**”转换为“MyStruct*”,但当我删除该命令时&已编译字符。谢谢你所做的一切@david这是因为你改变了问题中的代码。您声明了MyStruct*MyStruct
,这是一个错误。当我向struct中添加两个以上的字段时,会引发EAccessViolation异常。问题的根源是什么?如何调试此问题?------------------------------------调试器异常通知-----------------Project 1.exe引发异常类EAccessViolation,消息为“地址CCD处的访问冲突”。读取地址“CCD”。进程已停止。使用步骤或运行继续。----------------------------好的帮助-----------------你说得对。我只添加了int Z命名的字段。结构MyStruct{intx;双Y;intz;};这只是代码的一半。C代码也很重要。出于某种原因,打包了C++结构,而不是C++结构。不建议使用包装。这会导致数据不一致。为什么决定打包?我得到一个错误,行状态=DoSomething(5,5,&myStruct);[C++错误]Unit1.cpp(63):E2034无法将“MyStruct**”转换为“MyStruct*”,但当我删除该命令时&已编译字符。谢谢你所做的一切@david这是因为你改变了问题中的代码。您声明了MyStruct*MyStruct
,这是一个错误。当我向struct中添加两个以上的字段时,会引发EAccessViolation异常。问题的根源是什么?如何调试此问题?------------------------------------调试器异常通知-----------------Project 1.exe引发异常类EAccessViolation,消息为“地址CCD处的访问冲突”。读取地址“CCD”。进程已停止。使用步骤或运行继续。----------------------------好的帮助-----------------你说得对。我只添加了int Z命名的字段。结构MyStruct{intx;双Y;intz;};这只是代码的一半。C代码也很重要。出于某种原因,您打包了C#struct,但没有打包