まず、ネイティブ関数のプロトタイプを調整します。
この関数にはCインターフェースがあるため、ブール値にはC ++型ではなく、C型を使用する必要がありますbool
。Win32のBOOL
タイプを使用することをお勧めします。
さらに、現在のように、関数はバッファオーバーランを起こしやすいです。別のパラメータを追加して、宛先result
文字列バッファの最大サイズを指定することをお勧めします。
また、純粋なCインターフェイス関数(多くのWin32 API関数など)をエクスポートするDLLの一般的な呼び出し規約__stdcall
は(ではありません)であることに注意してください__cdecl
。私もそれを使います。
最後に、最初の2つのパラメーターは入力文字列であるため、これを使用const
して明確にし、const-correctnessを適用することをお勧めします。
したがって、エクスポートされたネイティブ関数のプロトタイプを次のように作成します。
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);
出力文字列にはaが使用されることに注意してくださいStringBuilder
。
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());
}
}
}