如何传递C ++ Struct到C#DLL? [英] How to pass C++ Struct To C# DLL?

查看:211
本文介绍了如何传递C ++ Struct到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆