从 VC 返回结构体++到 C#
我用VC++写了一个结构体。我已经制作了 VC++ 代码的 dll,并使用 PInvoke 在 C# 中调用此 dll。
VC++ dll 看起来像这样
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#if defined(_MSC_VER)
#include <windows.h>
#define DLL extern "C" __declspec(dllexport)
#else
#define DLL
#endif
struct SYSTEM_OUTPUT
{
int status;
};
DLL SYSTEM_OUTPUT* getStatus()
{
SYSTEM_OUTPUT* output;
output->status = 7;
return output;
}
我正在 C# 代码中从 dll 调用 getStatus() 函数,如下所示;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace UsingReturnStructDLL
{
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_OUTPUT
{
[MarshalAs(UnmanagedType.I4)]
int Status;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public SYSTEM_OUTPUT output;
[DllImport("ReturnStructDLL", EntryPoint = "getStatus")]
[return: MarshalAs(UnmanagedType.Struct)]
public extern static SYSTEM_OUTPUT getStatus();
private void button1_Click(object sender, EventArgs e)
{
try
{
SYSTEM_OUTPUT output = getStatus();
}
catch (AccessViolationException e)
{
label1.Text = e.Message;
}
}
}
}
我想在 C# 代码中检索结构中的值。通过上述代码设置,我收到以下错误;
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Int32/UInt32
must be paired with I4, U4, or Error).
有人可以帮我解决这个问题吗?
谢谢。
I have written a structure in VC++. I have made a dll of the VC++ code and calling this dll in C# using PInvoke.
The VC++ dll looks like this
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <iostream>
#if defined(_MSC_VER)
#include <windows.h>
#define DLL extern "C" __declspec(dllexport)
#else
#define DLL
#endif
struct SYSTEM_OUTPUT
{
int status;
};
DLL SYSTEM_OUTPUT* getStatus()
{
SYSTEM_OUTPUT* output;
output->status = 7;
return output;
}
I am calling the getStatus() function from the dll in my C# code, which looks as follows;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace UsingReturnStructDLL
{
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEM_OUTPUT
{
[MarshalAs(UnmanagedType.I4)]
int Status;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public SYSTEM_OUTPUT output;
[DllImport("ReturnStructDLL", EntryPoint = "getStatus")]
[return: MarshalAs(UnmanagedType.Struct)]
public extern static SYSTEM_OUTPUT getStatus();
private void button1_Click(object sender, EventArgs e)
{
try
{
SYSTEM_OUTPUT output = getStatus();
}
catch (AccessViolationException e)
{
label1.Text = e.Message;
}
}
}
}
I want to retrieve the values in the struct in my C# code. With the above setup of my code, I am getting the following error;
Cannot marshal 'return value': Invalid managed/unmanaged type combination (Int32/UInt32
must be paired with I4, U4, or Error).
Can someone please help me with the issue?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先让你的 C++ 代码工作。这是发布的垃圾,您没有初始化指针。它将因 AccessViolation 而崩溃。
在 C/C++ 中返回结构指针也非常,代码的客户端不知道需要如何释放内存。这也会对 P/Invoke 编组器造成严重破坏,它将尝试使用 CoTaskMemFree() 释放指针。这在 Vista 及更高版本上是一个大问题,在 XP 上是一个内存泄漏。
如果让客户端将指向结构的指针作为参数传递,所有这些问题都会消失:
然后在 C# 中变为:
Make your C++ code work first. It is junk as posted, you don't initialize the pointer. It will crash with an AccessViolation.
Returning pointers to structures is very hard to get right in C/C++ as well, the client of your code won't know how the memory needs to be released. Which plays havoc on the P/Invoke marshaller as well, it is going to try to release the pointer with CoTaskMemFree(). That's a kaboom on Vista and up, a memory leak on XP.
All of these problems disappear if you let the client pass a pointer to the structure as an argument:
Which then in C# becomes: