头文件
/*************************************************************************************************/ /*! \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).