如何将 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);