【问题标题】:Using C# Nested Structs In C++在 C++ 中使用 C# 嵌套结构
【发布时间】:2015-12-11 16:55:16
【问题描述】:

我在那个问题之前问过。

How to pass C++ Struct To C# DLL ?

现在我正在尝试嵌套结构元帅。

我已经替换了这样的结构。

typedef struct TKeyValue
{
  char Key[15];
  char Value[15];
} TKeyValue;

typedef struct MyStruct
{
  TKeyValue *KeyValues[1];
} TMyStruct;
typedef int (__stdcall *DoSomething)(char [],char[],TMyStruct *);

调用DLL函数

void __fastcall TForm1::btnInvokeMethodClick(TObject *Sender)
{
  wchar_t buf[256];
  String DLL_FILENAME = "ClassLibrary1.dll";
  HINSTANCE dllHandle = NULL;

  dllHandle = LoadLibrary(DLL_FILENAME.c_str());

  FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
  OutputDebugStringW(buf);

  if(dllHandle == NULL) return;

  DoSomething xDoSomething = (DoSomething)GetProcAddress(dllHandle, "DoSomething");
  FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
  OutputDebugStringW(buf);

  if (xDoSomething == NULL) return;

  try
  {
      TMyStruct aMyStruct;

      char parameter1[15];
      char parameter2[15];
      strcpy(parameter1,"value1");
      strcpy(parameter2,"value2");

      int result = xDoSomething(parameter1,parameter2,&aMyStruct);

      FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, NULL);
      OutputDebugStringW(buf);

      //access violation at this line
      ShowMessage(aMyStruct.KeyValue[0]->Key);
  }
  catch(EAccessViolation &err)
  {
    ShowMessage(err.Message);
  }

  FreeLibrary(dllHandle);

C#端

    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct KeyValue
    {
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
        public string Key;

        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
        public string Value;
    }



    [ComVisible(true)]
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct MyStruct
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        public KeyValue[] KeyValues;
    }

        [DllExport("DoSomething", CallingConvention = CallingConvention.StdCall)]
    public static int DoSomething(string tcKnVkn, string sifre, ref MyStruct myStruct)
    {
        try
        {
            MyStruct.KeyValues[0].Key = "key 1";
            MyStruct.KeyValues[0].Value = "value 1";
        }
        catch (Exception e)
        {
            System.Windows.Forms.MessageBox.Show(e.Message);
        }

        return 2;
    }

当我编译我的项目并运行时,它在像aMyStruct.KeyValue[0]->Key那样访问 TKeyValue 的 Key 字段后引发访问冲突错误

我怎么了?

谢谢。

【问题讨论】:

  • 删除除嵌套结构之外的所有内容。确保它有效。然后添加结构的嵌套数组。检查是否有效。等等。这就是调试的本质。首先隔离问题。
  • myStruct.KeyValues = new KeyValue[2] 看起来很奇怪。编组器不分配吗?无论如何,在你减少它并隔离问题并在两边显示完整的代码之前,我不会进一步研究,minimal reproducible example
  • 我已经修改了我的问题
  • 好吧,在 C++ 端,你有一个指向 struct 的指针数组,在 C# 端有一个 struct 数组。
  • 稍后我会尝试调试。我很困惑。谢谢

标签: c# c++ struct pinvoke marshalling


【解决方案1】:

这里的问题是你的Arrays 字段。 C++ 声明是:

char *Array[3];           // 3 pointers, uses up 12 bytes (32bit system)

这意味着一个包含 3 个指针的数组。稍等片刻,想想它离字符串有多远——它不是一个包含您要传递的字符的连续内存块,而是传递一个数字。如果您想传递 3 个 C 字符串,则可以这样声明(不是您发送的内容,您需要在 C# 端使用不同的属性):

char Array[15][3];        // 3 strings, uses up 45 bytes

您在这些指针中发送垃圾,当 C 代码试图取消引用它们时,它会遇到访问冲突。

【讨论】:

  • 他没有将该字段声明为字符串。他将其声明为[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public string[] Array;
  • 对,那个数组里面有什么?
  • string 的默认编组是 const char*
猜你喜欢
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
  • 2014-10-12
相关资源
最近更新 更多