Возвращение Struct из VC ++ в C # - PullRequest
       27

Возвращение Struct из VC ++ в C #

1 голос
/ 01 сентября 2010

Я написал структуру на VC ++. Я сделал DLL из кода VC ++ и вызывает эту DLL в C # с помощью PInvoke.

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;
}

Я вызываю функцию getStatus () из библиотеки DLL в моем коде на C #, которая выглядит следующим образом;

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).

Может кто-нибудь помочь мне с этой проблемой?

Спасибо.

Ответы [ 2 ]

3 голосов
/ 01 сентября 2010

Сделайте так, чтобы ваш код 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);
0 голосов
/ 21 февраля 2019
struct SYSTEM_OUTPUT
{
    int status; // try change to long
};
...