zoukankan      html  css  js  c++  java
  • C# PInvoke 方式调用 C/C++ 库 简单例子

    本文意在给出一个可用的 C# 调用 C/C++ lib 的实例。

    C/C++ lib

    C/C++ header

    #ifndef DPS_H
    #define DPS_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #if (defined _WIN32) || (defined _WINDOWS) || (defined WIN32)
    #ifdef MM_EXPORTS
    #define MMAPIEXP __declspec(dllexport)
    #else
    #define MMAPIEXP __declspec(dllimport)
    #endif
    #define MMAPI __cdecl
    #else
    #define MMAPIEXP
    #define MMAPI
    #endif
    
        // 定义一个回调
        typedef int(MMAPI *MMCallBack)(int handle, char* UserData);
    
        // 一个结构体
        typedef struct
        {
            int a;
            int b;
            char c;
            char* d;
        }DataInfo;
    
         // API 函数指针组成的结构体
        typedef struct
        {
            int (MMAPI* func01)(int a, int b);
            void (MMAPI* func02)(int c, DataInfo* d, MMCallBack cb);
        }MMAPIINFO;
    
          // 定义一个获取 API的函数,所有 API 通过该函数获取,注意,MMAPIEXP  用于指定WIN下导出函数名称
        MMAPIEXP  void  MMAPI GetAPI(MMAPIINFO* api);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    CPP 实现

    
    #include <cstddef>
    #include <cstring>
    #include "dps.h"
    
    // func01 函数实现
    int func01(int a, int b){
        return a + b;
    }
    
    // func01 函数实现
    void func02(int c, DataInfo* d, MMCallBack cb){
        cb(c,d->d);
    }
    
    // 定义获取 API 的函数
    void GetAPI(MMAPIINFO* api){
        if (api == NULL)
              return;
        memset(api, 0x00, sizeof(MMAPIINFO));
        api->func01 = func01;
        api->func02 = func02;
    }
    

    上述文件编译成为dll/lib. 对于C#而言,要调用的是dll. 上述文件可以生成为 dps.dll.
    注:名称无实际意义, 该代码自说明。

    C# 调用

    using System;
    using System.Runtime.InteropServices;
    
    namespace loadLib
    {
        class Program
        {
            static void Main(string[] args)
            {
                // 实例化一个 GetApi 类
                GetApi ss = new GetApi();
    
                Console.WriteLine(ss.Ffunc01(1,2));
    
                GetApi.DataInfo data = new GetApi.DataInfo
                {
                    a = 1,
                    b = 2,
                    c = 'x'
                };
                string str1 = "adbcd";
                data.d = str1;
    
                ss.Ffunc02(1024,ref data);
            }
        }
    
        class GetApi
        {
            // 特性定义了 MMAPIINFO 函数指针结构体的序列化方式和字符集
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct MMAPIINFO
            {
                public IntPtr func01;
                public IntPtr func02;
            }
    
            // 特性定义了 DataInfo 结构体的序列化方式和字符集
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public struct DataInfo
            {
                public int a;
                public int b;
                public char c;
                // char* 要使用 MarshalAs
                [MarshalAs(UnmanagedType.LPStr)]
                public string d;
            }
    
    
            // 委托函数MMCB的定义用于传入回调函数,对应于 dps.h 中的
            // int(MMAPI *MMCallBack)(int handle, char* UserData)
            // 特别注意:C# 回调函数的调用约定必须声明为 CallingConvention.Cdecl
            // 因为 C# 的调用约定是 __stdcall, 如果不指定调用约定,会默认 __stdcall,
            // 不同的调用约定会导致冲突
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            public delegate void MMCB(int handle, string userData);
    
            // 定义 MMAPIINFO.func01 的委托函数
            public delegate int Func01( int a, int b);
    
            // 定义 MMAPIINFO.func02 的委托函数
            public delegate void Func02(int c, ref DataInfo data, MMCB cbMmcb);
    
    
            // 封装函数,封装调用 MMAPIINFO.func01
            public int Ffunc01(int aa, int bb)
            {
                Func01 func = (Func01) Marshal.GetDelegateForFunctionPointer(A.func01, typeof(Func01));
                return func(aa, bb);
            
            }
    
            // 封装函数,封装调用 MMAPIINFO.func02
            public void Ffunc02(int c, ref DataInfo dat)
            {
                Func02 func = (Func02) Marshal.GetDelegateForFunctionPointer(A.func02, typeof(Func02));
                func(c, ref dat, apiCB);
            }
    
            // 成员变量 MMAPIINFO A 作为指针结构体
            public static MMAPIINFO A = new MMAPIINFO();
    
    
            // 声明 dsp.dll 的导出函数,注意调用约定 __cdecl 和字符集
            [DllImport("dps.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
            public static extern void GetAPI(ref MMAPIINFO param);
    
            // 构造函数用于从 dsp.dll 中获取api函数结构体
            public GetApi()
            {
                GetAPI(ref A);
            }
    
            // 实际传入的回调(被委托)函数
            public void apiCB(int handle, string userData)
            {
                Console.WriteLine(handle);
                Console.WriteLine(userData);
            }
        }
    }
    
  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/gardenofhu/p/13675969.html
Copyright © 2011-2022 走看看