回到C ++数组到C# [英] Return C++ arrays to C#

查看:251
本文介绍了回到C ++数组到C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想一个小的互操作的应用程序,其中我调用从C#的一些C ++的方法。我有一个非常简单的例子沃金用于调用方法并返回一个整数,它工作得很好。

I am trying a small interop application, in which I am invoking some C++ methods from C#. I have a very basic example woking for invoking a method and returning an integer, which works just fine.

InteropApp.h

#ifdef DLLFUNCTIONEXPOSETEST_EXPORTS
#define DLLFUNCTIONEXPOSETEST_API __declspec(dllexport)
#else
#define DLLFUNCTIONEXPOSETEST_API __declspec(dllimport)
#endif

extern "C" DLLFUNCTIONEXPOSETEST_API int fnSumofTwoDigits(int a, int b);



InteropApp.cpp

#include "stdafx.h"
#include "DLLFunctionExposeTest.h"
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    return TRUE;
}
DLLFUNCTIONEXPOSETEST_API int fnSumofTwoDigits(int a, int b)
{
    return a + b;
}



C#InteropAppTest

static class TestImport
    {
        [DllImport("DLLFunctionExposeTest.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "fnSumofTwoDigits")]
        public static extern int fnSumofTwoDigits(int a, int b);
    }
public partial class MainWindow : Window
    {
        public MainWindow()
        {
            try
            {
            InitializeComponent();
            int g = TestImport.fnSumofTwoDigits(2, 1);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }
}

在上面的C ++应用程序,我想要一个方法返回字符串的数组,而另一个方法返回的整数的数组。但是,正如我已经阅读做同样的,我很困惑,如果这会涉及编组?将方法的原型是什么样子都为C ++和C#?还有什么将改为调用C ++数组返回在C#应用程序的功能?

In the above C++ application, I want one method to return an array of strings, and another method to return an array of integers. But, as I have read to do the same, I am confused if this would involve marshalling? What would the method prototypes look like both for C++ and C#? What else would be changed to invoke the c++ array-returning function in C# app?

这将是巨大的,得到上述的事情一个简单的例子,因为我没' ŧ找到任何简单的如下手。

It would be great to get a simple example for the above thing, since I wasn't able to find any straightforward eg to start with.

推荐答案

有关此操作的建议方法是使用一个中间的C ++ / CLI项目(也被称为隐性的P / Invoke tecnique)。这样做对于涉及使用STL容器或复杂的类可以是令人沮丧的或不可能的任何明确的P / Invoke(的DllImport)。此外,它的输入不安全的:你必须猜测正确的签名做编组,往往有可能工作,这可能是混乱的多种可能性。在CLR在C ++(STL)的字符串和内部表示根本不匹配,所以你必须在它们之间转换,这使得和明确的P / Invoke编组痛苦的。

The recommended way for this is using an intermediate C++/CLI project (also called implicit P/Invoke tecnique). Doing explicit P/Invoke (DllImport) for anything that involves using stl containers or complex classes can be frustrating or impossible. Moreover it's type unsafe: you have to guess the correct signature to do the marshalling and often there are multiple possibilities that may work and this may be confusing. The internal representations of a string in C++(stl) and in the CLR simply don't match so you have to convert between them and this renders and explicit P/Invoke marshaling painful.

推荐的方法如下。请注意,我并没有编译代码,所以可能会有一些小的错误,但我可以保证,你也可以这样做。我已经做了很多次

The recommended way is the following. Please note I didn't compile the code so there may be some little errors, but I can ensure you it can be done in this way: I've done it plenty of times.

让说你在DLL本地项目(头Utils.h)有这样的:

Let say you have this in a DLL native project (header Utils.h):

DLLFUNCTIONEXPOSETEST_API std::vector<std::string> GetStrings();

请注意,重要的是要知道如何将这些字符串在C ++ STL内部编码::字符串(例如UTF-8,如果你是爽):

Please note that is important to know how those strings are internally encoded in the c++ stl::string (for example UTF-8 if you are cool):

现在您创建一个CRL C ++项目(UtilsW.h / UtilsW.cpp对):

Now you create a CRL C++ project (UtilsW.h/UtilsW.cpp pair ):

#include <Utils.h>

using namespace std;
using namespace System;
using namespace System::Text;
using namespace System::Collections::Generics;

namespace Interop
{
    public ref class Utils
    {
    public:
        static List<String ^> ^ GetStrings()
        {
            List<String ^> ^ret = gcnew List<String ^>();
            vector<string> strings = ::GetStrings();
            vector<string>::iterator begin = strings.begin();
            vector<string>::iterator end = strings.end();
            for (; it != end; it++)
                ret.Add(gcnew String((*it).c_str(), 0, (*it).lenght(), Encoding::UTF-8);
            return ret;
        }
    };
}

现在你用C#创建一个.NET项目,例如:

Now you create a .NET project for example in C#:

using Interop;

namespace NET
{
    public class Program
    {
        void foo()
        {
            List<string> strings = Utils.GetStrings();
            // Do something with strings
        }
    }
}

这篇关于回到C ++数组到C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆