LoginSignup
3
3

More than 3 years have passed since last update.

C++の資源をDLLを介してC#から使う(メモ)

Posted at

概要

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;
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3