美文网首页
DLL 封装动态链接库

DLL 封装动态链接库

作者: 码掺和_夏尼 | 来源:发表于2019-03-11 15:09 被阅读0次

    最近由于工作原因需要封DLL给客户用同时还要提供C#调用demo,这两个好几年都没用过了有点手生,趁热打铁记录一下以供回头查看。
    什么?你问我现在在干嘛?哦哦...我在玩儿iOS编程...半路出家自学的那种...好了废话不多说了开干吧(๑•̀ㅂ•́)و✧加油

    1.生成"C"的DLL

    vs编译器创建win32工程,并创建DLL工程(这里不展示创建,直白点好,直接上代码),然后code
    >>> test_dll.h

    #ifndef _TEST_DLL_HEADER_H_
    #define _TEST_DLL_HEADER_H_
    
    #if defined(TEST_DLL_EXPORT)
    #define DLL_API __declspec(dllexport)
    #else
    #define DLL_API __declspec(dllimport)
    #endif
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
        typedef struct {
        
            void(*on_start)(int code, void *param);
            void(*on_stop)(void *param);
        }test_callbacks;
    
        DLL_API void* create_handle(test_callbacks cb, void *param);
        DLL_API void start_handle(void *handle);
        DLL_API void stop_handle(void *handle);
        DLL_API void destroy_handle(void *handle);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    
    

    >>> test_dll.c

    ///define dll export macro
    #define TEST_DLL_EXPORT
    
    #include "test_dll.h"
    
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct {
    
        test_callbacks  callbacks;
        void*           callback_param;
    }test_handle;
    
    void* create_handle(test_callbacks cb, void *param) {
    
        test_handle *h = (test_handle*)malloc(sizeof(test_handle));
        if (NULL != h) {
    
            h->callbacks = cb;
            h->callback_param = param;
        }
        return h;
    }
    
    
    void start_handle(void *handle) {
    
        test_handle *h = (test_handle*)handle;
        printf(">>> start handle...\n");
        if (NULL != h && NULL != h->callbacks.on_start) {
    
            h->callbacks.on_start(404, h->callback_param);
        }
    }
    
    void stop_handle(void *handle) {
    
        test_handle *h = (test_handle*)handle;
        printf(">>> stop handle...\n");
        if (NULL != h && NULL != h->callbacks.on_stop) {
    
            h->callbacks.on_stop(h->callback_param);
        }
    }
    
    void destroy_handle(void *handle) {
    
        test_handle *h = (test_handle*)handle;
        if(NULL != h){
    
            free(h);
            h = NULL;
        }
    }
    

    2.调用DLL演示,在C中调用DLL

    >>> use_dll_in_c.c

    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>
    #include <strsafe.h>
    
    #include "test_dll.h"
    
    #define API_USE_DLL 1
    
    /// this way need header file
    #if !API_USE_DLL
    #pragma comment(lib, "dll_for_cs_demo.lib")
    #endif
    
    
    void test_start(int code, void *param) {
    
        printf(">>> [cb_start] code: %d\nparam: %s\n", code, (char*)param);
    }
    
    void test_stop(void *param) {
    
        printf(">>> [cb_stop] param: %s\n", (char*)param);
    }
    
    void PeerLastErrorMessage(PTCHAR function) {
    
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError();
        DWORD len = 0;
        char *str = NULL;
    
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)&lpMsgBuf,
            0, NULL);
    
        // Display the error message and exit the process
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
            (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)function) + 40) * sizeof(TCHAR));
        StringCchPrintf((LPTSTR)lpDisplayBuf,
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"),
            function, dw, lpMsgBuf);
    #if defined(UNICODE)
        len = WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)lpDisplayBuf, -1, NULL, 0, NULL, 0);
        str = (char*)malloc(sizeof(char) * (len + 1));
        WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)lpDisplayBuf, -1, str, len, NULL, 0);
        str[len] = '\0';
    #endif
        //MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
        printf("%s\n", str);
    
        free(str);
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
        //ExitProcess(dw);
    
    }
    
    typedef void* (*_create_h)(test_callbacks cb, void* param);
    typedef void(*_all_h)(void* param);
    
    int main(int argc, const char *argv[]) {
    
        int b = 0;
        void* handle = NULL;
        HMODULE mh = NULL;
        _all_h _handles = NULL;
        _create_h _create = NULL;
        test_callbacks cb = {test_start, test_stop};
    
    #if API_USE_DLL
        /// use dll
        mh = LoadLibrary(L"dll_for_cs_demo.dll");
        if (NULL == mh) {
    
            PeerLastErrorMessage(L">>> main");
            getchar();
            return EXIT_FAILURE;
        }
    
        _create_h _ch = (_create_h)GetProcAddress(mh, "create_handle");
        _all_h _sh = (_all_h)GetProcAddress(mh, "start_handle");
        _all_h _eh = (_all_h)GetProcAddress(mh, "stop_handle");
        _all_h _dh = (_all_h)GetProcAddress(mh, "destroy_handle");
    
        handle = _ch(cb, (void*)"haha");
        _sh(handle);
        _eh(handle);
        _dh(handle);
    #else
        /// use lib
        handle = create_handle(cb, (void*)"hehe");
        start_handle(handle);
        stop_handle(handle);
        destroy_handle(handle);
    #endif
    
        printf(">>> press anykey to exit...\n");
        getchar();
    
        return 0;
    }
    

    3.调用DLL演示,在C#中调用DLL

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    
    namespace use_dll_in_cs
    {
        class Program
        {
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            public delegate void on_start_d(int code, IntPtr param);
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            public delegate void on_stop_d(IntPtr param);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct callback
            {
                public on_start_d start_cb;
                public on_stop_d stop_cb;
            }
    
            [DllImport("dll_for_cs_demo.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "create_handle")]
            public extern static IntPtr create_handle(callback cb, IntPtr param);
    
            [DllImport("dll_for_cs_demo.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "start_handle")]
            public extern static IntPtr start_handle(IntPtr handle);
    
            [DllImport("dll_for_cs_demo.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stop_handle")]
            public extern static IntPtr stop_handle(IntPtr handle);
    
            [DllImport("dll_for_cs_demo.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroy_handle")]
            public extern static IntPtr destroy_handle(IntPtr handle);
    
            public static void test_start_cb(int code, IntPtr param)
            {
                Console.WriteLine(">>> [start_cb]: code: {0}, param: {1}", code, Marshal.PtrToStringAnsi(param));
            }
    
            public static void test_stop_cb(IntPtr param)
            {
                Console.WriteLine(">>> [stop_cb]: param: {0}", Marshal.PtrToStringAnsi(param));
            }
    
            static void Main(string[] args)
            {
                callback cb;
                cb.start_cb = test_start_cb;
                cb.stop_cb = test_stop_cb;
                IntPtr str_ptr = Marshal.StringToHGlobalAnsi("hello, c#");
                IntPtr handle = create_handle(cb, str_ptr);
                start_handle(handle);
                stop_handle(handle);
                Console.WriteLine("press any key to exit...");
                Console.ReadLine();
    
                destroy_handle(handle);
                Marshal.FreeHGlobal(str_ptr);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:DLL 封装动态链接库

          本文链接:https://www.haomeiwen.com/subject/bguduqtx.html