Връщане на Struct от VC++ към C#

Написах структура на 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).

Може ли някой да ми помогне с проблема?

Благодаря.


person Jayesh    schedule 01.09.2010    source източник
comment

Винаги съм използвал <%= some_code %> за вмъкване на Ruby в HTML, когато използвам Ruby on Rails. Току-що забелязах, че други проекти понякога използват <%= some_code -%>.

  -  person Mark H    schedule 01.09.2010
comment
Модифицирах го на: [DllImport(ReturnStructDLL, EntryPoint = getStatus)] [return: MarshalAs(UnmanagedType.LPStruct)] public extern static SYSTEM_OUTPUT getStatus(); ... но същата грешка   -  person Jayesh    schedule 01.09.2010


Отговори (1)


Първо накарайте вашия C++ код да работи. Това е боклук, както е публикувано, не инициализирате показалеца. Ще се срине с AccessViolation.

Връщането на указатели към структури е много трудно да се получи правилно и в C/C++, клиентът на вашия код няма да знае как паметта трябва да бъде освободена. Което прави хаос и на P/Invoke marshaller, той ще се опита да освободи показалеца с CoTaskMemFree(). Това е бум на Vista и по-нова версия, изтичане на памет на XP.

Всички тези проблеми изчезват, ако позволите на клиента да предаде указател към структурата като аргумент:

void getStatus(SYSTEM_OUTPUT* buffer)

Което след това в C# става:

[DllImport("mumble.dll")]
private static extern void getStatus(out SYSTEM_OUTPUT buffer);
person Hans Passant    schedule 01.09.2010
comment
Здравейте, ако накарам моя C# клиент да предава структурата като аргумент, как ще мога да задам стойността за члена на структурата в cpp. As-In върви по пътя ви, в c++, buffer.status = 7; дава ми грешка. Съжалявам, ако този въпрос е много шеговит, аз съм новак! Благодаря за помощта - person Jayesh; 01.09.2010
comment
Време е да се консултирате с книга за език C++. Това е буфер-›състояние = 7. - person Hans Passant; 01.09.2010