如何传递C ++ Struct到C#DLL? [英] How to pass C++ Struct To C# DLL?
问题描述
我有一个C#DLL下面喜欢。我想在C ++ Builder中使用这个C#DLL。
但我不知道C#Struct和C ++ Struct编组:
使用RGiesecke.DllExport;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
命名空间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#项目声明了struct参数,如下所示:
ref MyStruct myStruct
作为指向struct的指针。在C ++中表示
MyStruct *
因此,将函数指针变量的声明更改为:
int(__stdcall * DoSomething)(int,int,MyStruct *);
投放时使用相同类型:
DoSomething =(int(__stdcall *)(int,int,MyStruct *))GetProcAddress(dllHandle,DoSomething);
请注意,typedef会更好地帮助你避免重复自己。还要注意 GetProcAddress
不会引发异常。它通过返回 NULL
来通知错误。
调用函数时传递结构的地址:
<$> p $ p>
status = DoSomething(5,5,&myStruct);
声明 status
并将其初始化为-1,但随后重写该值。这是更习惯的声明和初始化它像这样:
int status = DoSomething(5,5,&myStruct) ;
I've a C# DLL below like. I want to use this C# DLL in C++ Builder.
But I don't know C# Struct and C++ Struct marshalling:
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;
}
}
}
I want to pass "myStruct" parameter from C++ Builder below like.
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);
}
}
}
When I debug code,myStruct.X and myStruct.Y value is wrong.
Where is my wrong ?
The C# project declares the struct parameter like this:
ref MyStruct myStruct
That marshals as a pointer to the struct. In C++ that means
MyStruct*
So change the declaration of the function pointer variable to be like so:
int (__stdcall *DoSomething)(int,int,MyStruct*);
And use the same type when you cast:
DoSomething =(int (__stdcall *)(int,int,MyStruct*)) GetProcAddress(dllHandle, "DoSomething");
Note that a typedef would serve you better here to avoid repeating yourself. And note also that GetProcAddress
does not raise exceptions. It signals errors by returning NULL
. You don't check for errors properly.
When you call the function pass the address of the struct:
status = DoSomething(5,5,&myStruct);
It's also a little pointless to declare status
and initialise it to -1, but then overwrite that value later. It would be more idiomatic to declare and initialise it like this:
int status = DoSomething(5,5,&myStruct);
这篇关于如何传递C ++ Struct到C#DLL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!