博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数委托_ZC
阅读量:6248 次
发布时间:2019-06-22

本文共 6901 字,大约阅读时间需要 23 分钟。

1、函数委托 类似于 C++中函数指针(∵我不知道这两货是否真的完全一样,∴用的是"类似于")

2、声明函数委托 方法类似于 声明函数指针

3、我的代码:

  3.1、VC的DLL代码:

// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***// 普通导出函数extern "C" __declspec(dllexport) int __stdcall TestZZ(int i, int j, int k, int m, int n){    return (i+j+k+m+n);}// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***// exe中传入回调函数指针,并且调用typedef int (__stdcall * Callback_Test01)(int, int, int, int, int);extern "C" __declspec(dllexport) void __stdcall TestCB(Callback_Test01 _callback){    if (_callback)    {        int i = _callback(1,2,3,4,5);    }}

    3.1.1、def文件内容:

LIBRARY DLL_ZEXPORTS    TestZZ    TestCB

  3.2、C#代码:

private void button1_Click(object sender, EventArgs e)        {            AAA(1, 2, 3); // 用汇编查看 调用普通C#函数时的调用规则            int kk = TestZZ(1, 2, 3, 4 ,5); // 查看调用DLL导出函数时的调用规则            Fhh = 0;            TestCB(callback);   // ZC: 将函数委托传递给 VC的DLL 并在DLL中调用 -- (1)            MessageBox.Show(Fhh.ToString());            Fhh = 0;            callback02 = new Callback_Test01(TT01);            TestCB(callback02); // ZC: 将函数委托传递给 VC的DLL 并在DLL中调用 -- (2)            MessageBox.Show(Fhh.ToString());        }        int AAA(int i, int j, int k)        {            return (i + j + k);        }        //[DllImport("DLL_Z.dll", EntryPoint="TestZZ", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]        [DllImport("DLL_Z.dll", EntryPoint = "TestZZ", CharSet = CharSet.Auto)]        public static extern int TestZZ(Int32 i, Int32 j, Int32 k, Int32 m, Int32 n);        [DllImport("DLL_Z.dll", EntryPoint = "TestCB", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]        public static extern void TestCB([MarshalAs(UnmanagedType.FunctionPtr)] Callback_Test01 _callback);        // (委托)回调函数指针        [UnmanagedFunctionPointer(CallingConvention.StdCall)]        public delegate int Callback_Test01(int _i, int _j, int _k, int _m, int _n);        public static int Fhh = 0;        // 委托(回调函数) -- 方式(1)        // 需要访问类成员变量的回调函数实例        Callback_Test01 callback =            (i, j, k, m, n) =>            {                Fhh = (i + j + k + m + n); // 这里可以直接访问 类成员变量                //return (i + j + k + m + n);                return Fhh;            };        Callback_Test01 callback02 = null;//new Callback_Test01(TT01);        // 委托(回调函数) -- 方式(2)        int TT01(int i, int j, int k, int m, int n)        {            Fhh = (i + j + k + m + n); // 这里可以直接访问 类成员变量            //return (i + j + k + m + n);            return Fhh;        }

  ZC: 测试感受:

  ZC: (1)、C#调用DLL中的函数,貌似默认的调用约定是 stdcall

  ZC: (2)、delegate 貌似它的默认调用约定也是stdcall

 

 

 

 

 

 

 

4、这里 测试的是 VC的DLL返回接口 让C#使用

  4.1、C#代码:

    4.1.1、接口声明

namespace WindowsFormsApplication_AAA{    [Guid("FCE9DCF3-9E38-441C-B10F-2BA31B57DCDC")]    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    public interface IntfTest    {        unsafe Int32 TestZ01(int _i, int _j, int _k, int* _piOut);        unsafe Int32 TestZ02(int _i, int _j, int _k, int _m, int* _piOut);        unsafe Int32 TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut);    }}

    4.1.2、

[DllImport("DLL_Z.dll", EntryPoint = "IntfTest_Get", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern int IntfTest_Get(ref IntfTest _intfTest);        private void button2_Click(object sender, EventArgs e)        {            callback02 = new Callback_Test01(TT01);            // 操作/使用 DLL返回的接口            IntfTest intfTest = null;            int iRtn = IntfTest_Get(ref intfTest);            unsafe            {                int iOut = 0;                intfTest.TestZ01(1, 2, 3, &iOut);            }        }

  4.2、VC的DLL中的代码:

    4.2.1、

// *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***// 导出 interface,供 exe使用IntfTest *g_pIntfTest;extern "C" __declspec(dllexport) int IntfTest_Get(IntfTest **_ppIntfTest){    (*_ppIntfTest) = NULL;    if ( NULL != g_pIntfTest )    {        // 当"IntfTest*"为局部变量时,C#会自动销毁接口,使得引用计数-1,∴这里需要+1        // 而 首次获取"IntfTest*"时,由于类构造函数中有增加引用计数的操作,∴不需要+1        g_pIntfTest->AddRef();        (*_ppIntfTest) = g_pIntfTest;        return 0;    }// ***    IntfTest *pObj = new TintfTest();    IUnknown *pIUnknown = NULL;    HRESULT hr = pObj->QueryInterface(IID_IUnknown, (void**)&pIUnknown);    pObj->Release();    pObj = NULL;    if (FAILED(hr))    {        return -1;    }    else    {        hr = pIUnknown->QueryInterface(IID_IntfTest, (void**)&g_pIntfTest);        pIUnknown->Release();        pIUnknown = NULL;        if (SUCCEEDED(hr))        {            (*_ppIntfTest) = g_pIntfTest;        }        else        {            return -2;        }    }    return 0;}

    4.2.2、接口信息:

#ifndef __zzz_20160414__#define __zzz_20160414__#include 
// // {FCE9DCF3-9E38-441C-B10F-2BA31B57DCDC}static const IID IID_IntfTest ={ 0xfce9dcf3, 0x9e38, 0x441c, { 0xb1, 0xf, 0x2b, 0xa3, 0x1b, 0x57, 0xdc, 0xdc } };interface IntfTest : public IUnknown{ virtual HRESULT __stdcall TestZ01(int _i, int _j, int _k, int* _piOut) = 0; virtual HRESULT __stdcall TestZ02(int _i, int _j, int _k, int _m, int* _piOut) = 0; virtual HRESULT __stdcall TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut) = 0;};class TintfTest :public IntfTest{public: TintfTest();public: virtual HRESULT __stdcall TestZ01(int _i, int _j, int _k, int* _piOut); virtual HRESULT __stdcall TestZ02(int _i, int _j, int _k, int _m, int* _piOut); virtual HRESULT __stdcall TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut);private: long FlCount;public: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppv) { if (iid == IID_IUnknown) { *ppv = static_cast
(this); } else if (iid == IID_IntfTest) { *ppv = static_cast
(this); } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } virtual ULONG STDMETHODCALLTYPE AddRef() { return ++FlCount; //return InterlockedIncrement(&FlCount); } virtual ULONG STDMETHODCALLTYPE Release() { if (--FlCount == 0) { delete this; return 0; } return FlCount; //if (InterlockedDecrement(&FlCount) == 0) //{ // delete this; // return 0; //} //return FlCount; }};TintfTest::TintfTest(): FlCount(0){ this->AddRef();}HRESULT __stdcall TintfTest::TestZ01(int _i, int _j, int _k, int* _piOut){ *_piOut = (_i + _j + _k); return S_OK;}HRESULT __stdcall TintfTest::TestZ02(int _i, int _j, int _k, int _m, int* _piOut){ return S_OK;}HRESULT __stdcall TintfTest::TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut){ return S_OK;}#endif // __zzz_20160414__

 

5、

 

转载于:https://www.cnblogs.com/csskill/p/5552798.html

你可能感兴趣的文章
微信公众平台开发(107) 分享到朋友圈和发送给好友
查看>>
推荐系统
查看>>
Appium安装过程
查看>>
Cocos2d-X中间应用
查看>>
Android学习笔记之SoftReference软引用...
查看>>
MFC office2007风格设置左侧导航栏 [转]
查看>>
swift:入门知识之泛型
查看>>
Git技巧:右键菜单怎么去除?
查看>>
【iCore3 双核心板_FPGA】例程四:Tcl脚本实验——配置引脚
查看>>
C4D to Unity3D插件C2U Tool开源发布!简化你的工作流
查看>>
【NLP】基于自然语言处理角度谈谈CRF(二)
查看>>
java.lang.OutOfMemoryError处理错误
查看>>
Innosetup中将bat文件压缩到压缩包中
查看>>
Android 手机卫士--签名文件说明&包名说明
查看>>
[转]python中@classmethod @staticmethod区别
查看>>
Linux排序不准确的问题,用以下两行代码解决
查看>>
MyBatis从入门到放弃一:从SqlSession实现增删改查
查看>>
为apache安装mod_wsgi的时候出现-fpic的问题
查看>>
Node,Sockets,Cores,Threads
查看>>
java数组和字符串相互转换
查看>>