スポンサーリンク

| キーワード:

C#からCのDLLにコールバック関数を渡す

C++のDLLの中に、関数ポインタを取る関数が外部に公開されている。

これをC#から使いたい。

どういうわけか、以下コードのCallFunctionに渡す関数ポインタの型をtypedefした関数ポインタ型(CallFP)にしたところランタイムエラーが起こる。

仕方がないので、void*で受け取って呼び出し直前にキャストするようにしたところうまくいった。今のところ、意味が分からない。

ちなみに、DLLDefs.hはDLL作成時に使用するヘッダで使っているもの。

dlltest.h

#include "DLLDefs.h"
#include <cstdint>
///////////////////////////////////
/// C++側 (ヘッダ) /////////////////
///////////////////////////////////
int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved);

typedef  void(WINAPI *CallFP)(std::int32_t a, std::int32_t b);

__DLL_PORT void WINAPI CallFunction(void* p,std::int32_t in1,std::int32_t in2);

 

dlltest.cpp

#include <Windows.h>
#include "dlltest.h"
///////////////////////////////////
/// C++側 (cpp) /////////////////
///////////////////////////////////
int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
  switch (dwReason) {
  case DLL_PROCESS_ATTACH:
    //初期処理
    break;
  case DLL_PROCESS_DETACH:
    //終了処理
    break;
  }

  return 1; // OK
};

void WINAPI CallFunction(void* p, std::int32_t in1, std::int32_t in2) {
  CallFP cp = static_cast<CallFP>(p);
  (*cp)(in1, in2);
}

 

using System;
using System.Runtime.InteropServices;//Marshal用
///////////////////////////////////
/// C#側 (呼び出し)/////////////////
///////////////////////////////////
namespace ConsoleApplication1
{
    //コールバック関数の型を宣言
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    delegate void TypeOfCallBack_t(System.Int32 a, System.Int32 b);

    class Program
    {
        //DLLの中の関数を宣言
        [DllImport("Project1.dll",EntryPoint = "CallFunction") ]
        public static extern void CallFunction(IntPtr callbk,Int32 in1,Int32 in2);

        //コールバック関数本体。この関数がDLL経由で呼び出される
        static public void CallBackMain(Int32 a, Int32 b)
        {
            Console.Write(a + b + "\n");
        }
        

        static TypeOfCallBack_t delgobj;
        static GCHandle gch;

        //エントリポイント
        public static void Main(string[] args)
        {
            delgobj = CallBackMain;
            IntPtr ptr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(
                delgobj
                );
            gch = GCHandle.Alloc(delgobj);

            //関数を呼び出す
            CallFunction( ptr ,10,15);

            Console.Read();

            gch.Free();
        }

    }
}

 

 

 

 

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: