首先,我会调整你的原生函数的原型。
由于这个函数有一个C 接口,你应该使用 C 类型的布尔值,而不是像bool
. 您可能想使用 Win32 的BOOL
类型。
此外,就目前而言,您的函数容易出现缓冲区溢出:最好添加另一个参数来指定目标result
字符串缓冲区的最大大小。
另请注意,导出纯 C 接口函数(如许多 Win32 API 函数)的 DLL 的广泛调用约定是__stdcall
(not __cdecl
)。我也会用那个。
最后,由于前两个参数是输入字符串,您可能希望使用const
它来明确并强制执行 const 正确性。
所以,我会像这样制作导出的本机函数的原型:
extern "C" __declspec(dllexport)
BOOL __stdcall NativeFunction(
const char *in1,
const char *in2,
char *result,
int resultMaxSize);
然后,在 C# 端,您可以使用以下 P/Invoke:
[DllImport(
"NativeDll.dll",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool NativeFunction(
string in1,
string in2,
StringBuilder result,
int resultMaxSize);
请注意,对于输出字符串,StringBuilder
使用了 a。
另请注意,CharSet = CharSet.Ansi
它用于将 C# 的 Unicode UTF-16 字符串编组为 ANSI(请注意转换是有损的- 如果您想要无损转换,也只需wchar_t*
在 C++ 端使用字符串)。
我用一个简单的 C++ 本地 DLL 做了一个测试:
// NativeDll.cpp
#include <string.h>
#include <windows.h>
extern "C" __declspec(dllexport)
BOOL __stdcall NativeFunction(
const char *in1,
const char *in2,
char *result,
int resultMaxSize)
{
// Parameter check
if (in1 == nullptr
|| in2 == nullptr
|| result == nullptr
|| resultMaxSize <= 0)
return FALSE;
// result = in1 + in2
strcpy_s(result, resultMaxSize, in1);
strcat_s(result, resultMaxSize, in2);
// All right
return TRUE;
}
它被以下 C# 控制台应用程序代码成功调用:
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace CSharpClient
{
class Program
{
[DllImport(
"NativeDll.dll",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool NativeFunction(
string in1,
string in2,
StringBuilder result,
int resultMaxSize);
static void Main(string[] args)
{
var result = new StringBuilder(200);
if (! NativeFunction("Hello", " world!", result, result.Capacity))
{
Console.WriteLine("Error.");
return;
}
Console.WriteLine(result.ToString());
}
}
}