概要
C++ 側と c# 側とで可変長文字列をやり取りする際のメモリの扱いが異なり、癖があるのでメモ。
C++ 側に文字列を引数で渡し、【戻り値】で受け取る方法
DllTest.cs(C#)
[TestClass]
public class DllTest
{
[DllImport("MyDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.LPStr)]
static extern string DllTestMethod(string hoge);
[TestMethod]
public void CanPassAndReceiveStringToDll()
{
string output = DllTestMethod("ああ");
Assert.AreEqual("ああてすと", output);
}
}
API.h(C++)
# pragma once
# define DllExport __declspec( dllexport )
extern "C"
{
DllExport int __stdcall DllTestMethod(char* hoge);
}
API.cpp(C++)
# include "stdafx.h"
# include <iostream>
# include "API.h"
char* CStringToChar(LPCWSTR pStr) {
// 変換後に必要なメモリサイズ取得
int iByte = WideCharToMultiByte(CP_ACP, 0, pStr, -1, NULL, 0, NULL, NULL);
// 文字列格納領域確保
char* pszReturn = (char*)::CoTaskMemAlloc(iByte);
// 変換
WideCharToMultiByte(CP_ACP, 0, pStr, -1, pszReturn, iByte, NULL, NULL);
return pszReturn;
}
char* CStringToChar(CString str) {
// 変換元取得
LPCWSTR pStr = str.GetString();
return CStringToChar(pStr);
}
char* __stdcall DllTestMethod(char* hoge)
{
std::cout << "Call C DLL!! - [" << hoge << "]" << std::endl;
return CStringToChar(CString(hoge) + _T("てすと"));
}
C++ 側に文字列を引数で渡し、【引数】で受け取る方法
DllTest.cs(C#)
[TestClass]
public class DllTest
{
[DllImport("MyDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
static extern int DllTestMethod(string hoge, [MarshalAs(UnmanagedType.LPStr), Out] out string output);
[TestMethod]
public void CanPassAndReceiveStringViaDll()
{
int res = CanPassAndReceiveStringToDll("ああ", out string output);
Assert.AreEqual(res, 123);
Assert.AreEqual(output, "ああてすと");
}
}
API.h(C++)
# pragma once
# define DllExport __declspec( dllexport )
extern "C"
{
DllExport int __stdcall DllTestMethod(char* hoge, const char** output);
}
API.cpp(C++)
# include "stdafx.h"
# include <iostream>
# include "API.h"
char* CStringToChar(LPCWSTR pStr) {
// 変換後に必要なメモリサイズ取得
int iByte = WideCharToMultiByte(CP_ACP, 0, pStr, -1, NULL, 0, NULL, NULL);
// 文字列格納領域確保
char* pszReturn = (char*)::CoTaskMemAlloc(iByte);
// 変換
WideCharToMultiByte(CP_ACP, 0, pStr, -1, pszReturn, iByte, NULL, NULL);
return pszReturn;
}
char* CStringToChar(CString str) {
// 変換元取得
LPCWSTR pStr = str.GetString();
return CStringToChar(pStr);
}
int __stdcall DllTestMethod(char* hoge, const char** output)
{
std::cout << "Call C DLL!! - [" << hoge << "]" << std::endl;
*output = CStringToChar(CString(hoge) + _T("てすと"));
return 123;
}