编辑
2022-06-07
编程语言
00
请注意,本文编写于 483 天前,最后修改于 113 天前,其中某些信息可能已经过时。

有时候需要C#调用C/C++库,如果是异步调用必然涉及回调函数,本文记录一下C#如何调用C++以及如何处理Native的回调。首先生成Windows下的动态库 DLL可以参考:《演练:创建和使用自己的动态链接库 (C++)》,由于是在Windows环境,所以没有做关于平台区分的宏定义。

Windows下生成动态库DLL,也就是导出操作:

c++
#pragma once typedef int(__stdcall* func_notice)(int, int); extern "C" { __declspec(dllexport) void __stdcall my_print(); __declspec(dllexport) int __stdcall calc_add(int a, int b); __declspec(dllexport) void __stdcall setNotice(func_notice func); }

使用动态库DLL,也就是导入操作:

c++
#pragma once typedef int(__stdcall* func_notice)(int, int); extern "C" { __declspec(dllimport) void __stdcall my_print(); __declspec(dllimport) int __stdcall calc_add(int a, int b); __declspec(dllimport) void __stdcall setNotice(func_notice func); }

func_notice 是一个函数指针,即是定义的回调函数。头文件定义了,具体实现如下(就简单实现一下):

c++
#include <stdio.h> #include "calc.h" func_notice call_back = NULL; void my_print() { printf("my_print exec..\n"); } int calc_add(int a, int b) { printf("calc_add exec.. a = %d, b = %d\n", a, b); if (call_back) { printf("call_back exec..\n"); call_back(a + 10, b + 10); } return a + b; } void setNotice(func_notice func) { call_back = func; }

本地使用测试一下,测试没问题就通过C#来调用。

c++
#include "calc.h" #include <iostream> int my_func(int a, int b) { printf("my_func callback success! a = %d, b = %d\n", a, b); return 0; } int main() { setNotice(my_func); my_print(); printf("calc_add -> %d", calc_add(50, 100)); return 0; }

C# 如何使用调用DLL(同样的DLL和exe放在同一个文件夹底下):

c#
using System; using System.Runtime.InteropServices; namespace CSCallTest { class Program { // 定义回调方法 public static int CallBackFunction(int a, int b) { Console.WriteLine("C++ call me, a = " + a + ", b = " + b); return a + b; } static void Main(string[] args) { DllImportX.CallbackDel callback = CallBackFunction; DllImportX.my_print(); DllImportX.setNotice(callback); int calcAdd = DllImportX.calc_add(20, 90); Console.WriteLine("calcAdd = " + calcAdd); } } public class DllImportX { [DllImport("call_test.dll", EntryPoint = "my_print", CallingConvention = CallingConvention.StdCall)] public static extern void my_print(); [DllImport("call_test.dll", EntryPoint = "calc_add", CallingConvention = CallingConvention.StdCall)] public static extern int calc_add(int a, int b); [DllImport("call_test.dll", EntryPoint = "setNotice", CallingConvention = CallingConvention.StdCall)] public static extern void setNotice(CallbackDel callback); // 定义委托 public delegate int CallbackDel( [MarshalAs(UnmanagedType.I4)] int a, [MarshalAs(UnmanagedType.I4)] int b ); } }

UnmanagedType.XXX 对应表格,类型需要对应,参考地址 UnmanagedType Enum

参考资料:

1、UnmanagedType Enum

2、演练:创建和使用自己的动态链接库 (C++)

本文作者:Tim

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!