C#から自作のC++DLLのクラスを呼び出す方法

投稿者: Anonymous

UnityC#にて重たい処理をDLLにやってもらおうと思い、
ViusalStudioを用いてC++のDLLをこちらを参考に作成しました。

メソッドを呼び出すことはできたので、
今度はクラス経由で呼び出してみようと思い
C++側のクラスの定義をMSDNのここを参考にクラスを作成したのですが
C#側からどのように呼び出せばいいのかがわかりません。


C#側

using UnityEngine;
using System.Collections;

// Must Need DLL Import 
using System.Runtime.InteropServices;

public class CallDlls : MonoBehaviour {

    // From c++ Dll (unmanaged)
    [DllImport("MathFuncsDll")]
    public static extern float TestMultiply(float a, float b);

    // From c++ Dll (unmanaged)
    [DllImport("MathFuncsDll")]
    public static extern float TestDivide(float a, float b);

    public float multiply(float a,float b)
    {
        return TestMultiply(a, b);
    }
}

C++DLL側

// MathFuncsDll.cpp

#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>

using namespace std;

extern "C" {
float TestMultiply(float a, float b)
{
    return a * b;
}

float TestDivide(float a, float b)
{
    if (b == 0) {
        return 0;
        //throw invalid_argument("b cannot be zero!");
    }

    return a / b;
    }
}

// MathFuncsDll.h

#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif

extern "C" {
    class MATHFUNCSDLL_API TestClass {
        float TestMultiply(float a, float b);
        float TestDivide(float a, float b);
        //MATHFUNCSDLL_API float TestMultiply(float a, float b);
        //MATHFUNCSDLL_API float TestDivide(float a, float b);
    };
}

解決

技術的にはC#コードから直接C++クラスのメンバ関数を呼ぶことも可能です。ただし、幾つかの理由からお薦めできません。@時計屋さん回答にある解決策を採用したほうがよいと思います。

DLL/C++クラスのメンバ関数はthiscall呼出し規約(calling convention)をもちますので、DllImport属性でCallingConvention.ThisCallを指定し、EntryPointには”マングリングされた関数名”を指定する必要があります。詳細は記事 How to Marshal a C++ Class が参考になります。

お薦めできない理由:

  • DLL/C++側クラスのコンストラクタ/デストラクタを、C#側から直呼び出すことはできません。少なくともC++クラスオブジェクトのnew/delete操作を行うC++側にヘルパー関数が必要です。
  • DLL/C++側でエクスポートされる”マングリングされた関数名”に、C#側では常に追従させる必要があるためメンテナンスコストが高くなります。
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *