`

C#使用C++标准DLL实例(包含callback)

 
阅读更多
C++编写标准Win32DLL如下

头文件
/*************************************************************************************************/
/*!
    \file CppDll.h

    \attention
        Copyright (c) 2016  Jacky_Dai.
        All Rights Reserved.
*/
/*************************************************************************************************/
#ifndef CPP_DLL_H
#define CPP_DLL_H

/*** Defines/Macros/Constants/Typedefs ***********************************************************/
#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif

//Include Head files
//////////////////////////////////////////////////////////////////////////
#include <Windows.h>



#ifdef __cplusplus
extern "C"
{
#endif

/*************************************************************************************************/
/*!
    \brief CPP_CALLBACK 
    The callback for test.

    Note: Out put test data

    \param[out]  pbySignatureData - Reserved buffer for writing signature.
    \param[in/out]  pdwSignatureDataSize - The reserved data size / Used data size

    \return  Return ERR_OK if the function succeeds else nonzero error code.
*/
/*************************************************************************************************/
typedef DWORD (CALLBACK *CPP_CALLBACK)(PBYTE pbySignatureData, DWORD pdwSignatureDataSize);

CPPDLL_API DWORD TestApp1(BYTE* pByInBuffer,
                               DWORD dwInSize,
                               BYTE* pByOutBuffer,
                               DWORD* pdwOutSize);

CPPDLL_API DWORD TestApp2(BYTE* pByInBuffer,
                                DWORD dwInSize,
                                BYTE* pByOutBuffer,
                                DWORD* pdwOutSize,
                                CPP_CALLBACK pCallback);

CPPDLL_API DWORD TestApp3(DWORD dwVal);

CPPDLL_API DWORD TestApp4(DWORD* pdwVal);

#ifdef __cplusplus
}
#endif

#endif//CPP_DLL_H



源代码
#include "CppDll.h"
#include "stdio.h"
#include <string.h>
#include <time.h>

DWORD TestApp1(BYTE* pByInBuffer,
                   DWORD dwInSize,
                   BYTE* pByOutBuffer,
                   DWORD* pdwOutSize)
{
    if (pByOutBuffer!=NULL && pdwOutSize != NULL)
    {
        CHAR szTemp[1024] = {0};
        sprintf(szTemp, "[CppDll][%s] catch en error in line(%d).\r\n", __FUNCTION__, __LINE__);

        if (*pdwOutSize >= strlen(szTemp))
        {
            *pdwOutSize = (DWORD)strlen(szTemp);
            memcpy(pByOutBuffer, szTemp, strlen(szTemp));
        }
        else
        {
            *pdwOutSize = 0;
        }
    }

    return 0x0201;
}


DWORD TestApp2(BYTE* pByInBuffer,
                   DWORD dwInSize,
                   BYTE* pByOutBuffer,
                   DWORD* pdwOutSize,
                   CPP_CALLBACK pCallback)
{
    if (pByOutBuffer!=NULL && pdwOutSize != NULL)
    {
        CHAR szTemp[1024] = {0};
        sprintf(szTemp, "[CppDll][%s] catch en error in line(%d).\r\n", __FUNCTION__, __LINE__);

        if (*pdwOutSize >= strlen(szTemp))
        {
            *pdwOutSize = (DWORD)strlen(szTemp);
            memcpy(pByOutBuffer, szTemp, strlen(szTemp));

            if (pCallback != NULL)
            {
                CHAR szCallbackTemp[1024] = {0};
                sprintf(szCallbackTemp, "[CppDll][%s] Callback output data in line(%d).\r\n", __FUNCTION__, __LINE__);

                pCallback((PBYTE)(szCallbackTemp), (DWORD)strlen(szCallbackTemp));
            }
        }
        else
        {
            *pdwOutSize = 0;
        }
    }

    Sleep(500);
    return 0x0205;
}

CPPDLL_API DWORD TestApp3(DWORD dwVal)
{
    if (0 == dwVal)
    {
        return 0;
    }

    return 1;
}

CPPDLL_API DWORD TestApp4(DWORD* pdwVal)
{
    if (NULL != pdwVal)
    {
        *pdwVal = 256;
        return 0;
    }

    return 1;
}



C#写的测试代码如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;//DllImport
using System.Diagnostics;//Debug

namespace CSharpUsingCppCallbackDemo
{
    public partial class Form1 : Form
    {
        public delegate uint CppCallback([MarshalAs(UnmanagedType.LPArray, SizeConst = 1024)]byte[] byOutBuffer, uint outSize);


        private const string testDll = @"C:\Users\jacky_dai\Desktop\CSharpUsingCppCallbackDemo\Debug\CppDll.dll";

        [DllImport(testDll)]
        public static extern uint TestApp1([In]byte[] inBuffer, [In]uint inSize, [In][Out]byte[] byOutBuffer, [In][Out]ref uint outSize);

        [DllImport(testDll)]
        public static extern uint TestApp2([In]byte[] inBuffer, [In]uint inSize, [In][Out]byte[] byOutBuffer, [In][Out]ref uint outSize, CppCallback pCallback);

        [DllImport(testDll)]
        public static extern uint TestApp3([In]uint dwVal);

        [DllImport(testDll)]
        public static extern uint TestApp4([In][Out]ref uint dwVal);


        public Form1()
        {
            InitializeComponent();
        }

        public uint TestCallback(/*[MarshalAs(UnmanagedType.LPArray, SizeConst=1024)]*/byte[] byOutBuffer, uint outSize)
        {

            string strMsg = System.Text.Encoding.Default.GetString(byOutBuffer);
            Debug.WriteLine(strMsg);

            return 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            uint ret = 0;
            byte[] helloBuf = new byte[2048];
            byte[] tempbuffer = new byte[2048];
            uint bufSize = 2048;

            //ret = TestApp3(bufSize);
            //ret = TestApp4(ref bufSize);

            //ret = TestApp1(helloBuf, ret, tempbuffer, ref bufSize);

            ret = TestApp2(helloBuf, ret, tempbuffer, ref bufSize, new CppCallback(TestCallback));

            string strMsg = System.Text.Encoding.Default.GetString(tempbuffer);
            Debug.WriteLine(strMsg);
        }
    }
}



[CppDll][TestApp2] Callback output data in line(50).
[CppDll][TestApp2] catch en error in line(40).
分享到:
评论

相关推荐

    c#调用C++ 的DLL带有CALLback

    本文将详细介绍如何在C#中调用一个C++ DLL,并处理其中包含的CALLBACK回调函数。 #### C#调用C++ DLL的基本原理 在C#中调用C++ DLL主要依赖于平台调用服务(Platform Invoke Services,简称P/Invoke),这是一种...

    C#调用C++的dll实例,回调函数,string和int数组参数传递

    本实例将详细介绍如何在C#中调用C++的DLL,并处理回调函数、字符串和整型数组参数的传递。 首先,C++的DLL需要定义导出函数,以便C#能够访问。这些函数通常使用`extern "C"`来避免C++的名称修饰,以确保C#能正确...

    C#调用c++函数的dll文件,同时实现c++调用c#函数

    总的来说,C#调用C++ DLL和C++调用C#函数是通过.NET Framework的互操作特性实现的,包括P/Invoke和C++/CLI。这种方式在处理系统级操作、利用现有C++库或需要高性能计算时非常有用。解压后的两个项目"Dll3"和...

    C++ DLL C# CALLBACK

    标题“C++ DLL C# CALLBACK”暗示了我们将探讨如何在C++编写的DLL中定义回调函数,然后在C#应用程序中调用这个DLL并传递一个回调函数作为参数。回调函数允许DLL在执行过程中调用客户端代码,从而实现更复杂的交互。 ...

    C#调用C++DLL

    在C#中,我们可以创建一个方法并传递它的委托实例给C++DLL: ```csharp public static void Main(string[] args) { CallbackDelegate myCallback = MyCallbackMethod; CustomStruct customData = new ...

    C#调用C++动态库中自身定义的回调函数

    C++ DLL项目将包含定义的接口和回调函数,而C#项目则负责调用这些函数并提供回调实现。 在C++库中,你需要定义一个函数原型,该函数接受一个指向回调函数的指针。例如: ```cpp extern "C" __declspec(dllexport) ...

    C#调用C++动态库,执行回调函数并传递结构体参数

    总结来说,这个工程示例展示了C#和C++之间的深度交互,包括P/Invoke调用,回调函数的使用,以及结构体参数的传递。这需要对C#和C++的内存管理、调用约定和数据类型有深入理解。对于需要跨语言交互的开发者来说,这样...

    基于C#调用c++Dll结构体数组指针的问题详解

    基于C#调用C++ Dll结构体数组指针的问题详解 C#调用C++ Dll文件是一件很麻烦的事情,首先面临的是数据类型转换的问题。相信经常做C#开发的都和...C#调用C++ Dll文件需要注意数据类型的转换和结构体数组的申明和使用。

    c++ 与c#的中文字符串传递演示demo

    - 在C#中使用`DllImport`时,提供正确的DLL名和函数原型,包括参数类型、顺序和调用约定。 - 关注内存管理,C++和C#有不同的内存管理机制,需要确保在适当的时机释放分配的内存。 通过以上步骤,我们可以在C++和...

    C#_DLL_OpenCv_VS2012.zip_C#_c# c++ opencv dll_dll_opencv_opencv2

    在本项目中,我们主要探讨如何使用C#调用OpenCV库通过DLL文件在Visual Studio 2012环境下开发一个应用程序,实现摄像头视频的播放功能。OpenCV(Open Source Computer Vision Library)是一个强大的计算机视觉库,它...

    C# 调用 C++ 动态库并调用自身注册到动态库的函数

    C++ DLL中的函数需要遵循特定的约定,即标准的C调用约定(__stdcall),以便C#能够正确地识别和调用这些函数。在C++中,我们可以定义一个函数指针类型,然后在C#中声明对应的委托类型,这个委托类型与C++的函数指针...

    c#调用qt dll

    - 正确地定义C#接口以匹配DLL函数的签名,包括参数类型和调用约定。 - 对于回调函数,使用委托在C#中封装方法,并传递给DLL。 - 注意内存管理,特别是字符串和自定义类型,因为C#和C++有不同的内存模型。 正确理解...

    VC/C#调用delphi写的dll, 演示如何进行类的传递并callback调用方的代码

    在Delphi中创建DLL,然后在VC或C#中调用,可以利用Delphi的强大面向对象特性,并将其集成到C++项目中。 首先,让我们理解一下Delphi DLL的创建过程。在Delphi中,你可以定义一个接口(Interface),它包含了要导出...

    c++回调c#方法

    不过,借助.NET Framework的互操作性特性,如C++/CLI(C++针对.NET的扩展)和P/Invoke(Platform Invoke),我们可以实现C++回调C#方法,同时传递包含结构体的数据。下面我们将深入探讨这个主题。 首先,我们需要...

    C#委托与C++回调函数处理

    在C#中,你需要定义一个对应的委托类型,并使用`DllImport`属性导入C++的DLL函数。例如: ```csharp [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void MyCppCallback(int result); ...

    c++和c#键盘钩子

    2. **API调用**:C++直接使用Windows API,而C#通过P/Invoke间接调用。 3. **内存管理**:C++需要手动管理内存,C#则由垃圾回收机制自动处理。 4. **代码结构**:C++代码可能更为底层和直接,而C#代码通常更简洁、...

    C#中用委托实现C++的回调函数

    本文将探讨如何在C#中使用委托实现C++的回调函数,并结合VS2015和VS2019环境,讨论如何处理UDP快速通信中的数据收发,包括数组的传递。 首先,理解C#中的委托。委托是C#中的一种类型,类似于C++的函数指针,可以...

    C# 全局勾子(Hook 含鼠标键盘窗口内核等)

    C#全局钩子的实现通常涉及到使用C++编写一个动态链接库(DLL),因为Windows API的钩子函数通常是C语言风格的,然后在C#应用程序中调用这个DLL来设置和处理钩子。本文将深入探讨C#全局钩子的实现原理、步骤以及如何...

Global site tag (gtag.js) - Google Analytics