从 VC 返回结构体++到 C#

发布于 2024-09-16 20:50:36 字数 1825 浏览 5 评论 0原文

我用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人心善变 2024-09-23 20:50:36

首先让你的 C++ 代码工作。这是发布的垃圾,您没有初始化指针。它将因 AccessViolation 而崩溃。

在 C/C++ 中返回结构指针也非常,代码的客户端不知道需要如何释放内存。这也会对 P/Invoke 编组器造成严重破坏,它将尝试使用 CoTaskMemFree() 释放指针。这在 Vista 及更高版本上是一个大问题,在 XP 上是一个内存泄漏。

如果让客户端将指向结构的指针作为参数传递,所有这些问题都会消失:

void getStatus(SYSTEM_OUTPUT* buffer)

然后在 C# 中变为:

[DllImport("mumble.dll")]
private static extern void getStatus(out SYSTEM_OUTPUT buffer);

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:

void getStatus(SYSTEM_OUTPUT* buffer)

Which then in C# becomes:

[DllImport("mumble.dll")]
private static extern void getStatus(out SYSTEM_OUTPUT buffer);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文