返回 C++数组到 C#
我正在尝试一个小型互操作应用程序,其中我从 C# 调用一些 C++ 方法。我有一个非常基本的示例,用于调用方法并返回整数,效果很好。
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++ 应用程序中,我希望有一个方法返回字符串数组 code>,以及另一个返回
整数数组
的方法。但是,正如我读到的那样,我很困惑这是否涉及编组? 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());
}
}
}
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
建议的方法是使用中间 C++/CLI 项目(也称为隐式 P/Invoke 技术)。对涉及使用 stl 容器或复杂类的任何内容进行显式 P/Invoke (DllImport) 可能会令人沮丧或不可能。此外,它的类型不安全:您必须猜测正确的签名才能进行编组,并且通常有多种可行的可能性,这可能会令人困惑。 C++(stl) 和 CLR 中字符串的内部表示根本不匹配,因此您必须在它们之间进行转换,这会导致渲染和显式 P/Invoke 封送处理变得很痛苦。
推荐的方法如下。请注意,我没有编译代码,因此可能会有一些小错误,但我可以向您保证它可以通过这种方式完成:我已经这样做了很多次。
假设您在 DLL 本机项目(标头 Utils.h)中有这个:
请注意,了解这些字符串在 c++ stl::string 中如何内部编码非常重要(例如 UTF-8,如果您很酷的话):
现在您创建一个 CRL C++ 项目(UtilsW.h/UtilsW.cpp 对):
现在您创建一个 .NET 项目,例如在 C# 中:
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.
Let say you have this in a DLL native project (header Utils.h):
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):
Now you create a CRL C++ project (UtilsW.h/UtilsW.cpp pair ):
Now you create a .NET project for example in C#:
如果您不必在 C++ dll 中分配数组,则可以将空整数数组传递给函数并让它填充那里。这适用于默认编组。
但是,您无法将 std::string 封送至 C#,因为此类未知。您必须将字符串作为 C 字符串传递,最好是 wchar_t*。
请参阅:http://msdn.microsoft.com/en-us/library/bd99e6zt .aspx
If you do not have to allocate the array in the C++ dll, you can pass an empty integer array to the function and let it fill there. This works with default marshalling.
However you cannot marshal std::string to C# as this class is not known. You have to pass strings as C strings, preferably wchar_t*.
See: http://msdn.microsoft.com/en-us/library/bd99e6zt.aspx