前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MFC 调用静态链接 MFC 的规则 DLL

MFC 调用静态链接 MFC 的规则 DLL

作者头像
包子388321
发布2020-06-16 19:17:23
2.5K0
发布2020-06-16 19:17:23
举报
文章被收录于专栏:包子的书架包子的书架
简语:

最近学习了生成静态链接的dll及其调用,写一下笔录和大家分享,有错误的地方欢迎大家指出来

开发环境

VS2015

开发语言

C++

开发步骤

以mfc的dll创建为例,先说明一下win32的dll和mfc的dll在支持C上,win32可能比较好,实现的过程是一样的。

构建MFC的DLL项目
  • 新建MFC DLL项目
  • 这边选择带静态链接MFC的规则DLL
  • 默认生成了,头文件和源文件,右键def文件
  • MyDLL.h 个人是将整个类导出,也可以单独导出某个或者几个函数 导出函数是 :__declspec(dllimport) void(类型) __stdcall 函数名 导出类具体参考msdn
代码语言:java
复制
// MyDLL.h : MyDLL DLL 的主头文件
#pragma once
#ifndef __AFXWIN_H__
    #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"       // 主符号

#define EXPORT __declspec(dllimport)  //这边是导出的宏定义


/**
* 接口测试接口回调
* @param code 初始化成功返回code码
*/
typedef void(*TestCallBack)(int code);

/**
* 测试结果接口回调
* @param result 返回测试结果
*/
typedef void(*TestResultCallBack)(const char* result);

/**
*
*/
typedef struct TestInfo {
    int No;
    const char* name;
    const char* content;
} TestInfo;

// CMyDLLApp
// 有关此类实现的信息,请参阅 MyDLL.cpp
// 对外导出 CMyDllApp类


class EXPORT CMyDLLApp      //将整个类导出,也可以单独导出单个函数
{
// 重写
public:

    TestCallBack testCallBack;
    TestResultCallBack resultCallBack;
    TestInfo info;
    char* id;

    void __stdcall InitTest(TestInfo const& info, char* id);
    void __stdcall SetTestCallBack(TestCallBack testCallBack);
    void __stdcall SetResultCallBack(TestResultCallBack resultCallBack);
    char* __stdcall GetTestInfoCode();

    void OnCalculate();
    void DoTest();
};
  • MyDLL.cpp 这边是逻辑实现
代码语言:javascript
复制
// MyDLL.cpp : 定义 DLL 的初始化例程。
//

#include "stdafx.h"
#include "MyDLL.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

void CMyDLLApp::InitTest(TestInfo const & info, char * id)
{
    this->info = info;
    this->id = id;
}

void CMyDLLApp::SetTestCallBack(TestCallBack testCallBack)
{
    this->testCallBack = testCallBack;
    OnCalculate();
}

void CMyDLLApp::SetResultCallBack(TestResultCallBack resultCallBack)
{
    this->resultCallBack = resultCallBack;
    DoTest();
}

char * CMyDLLApp::GetTestInfoCode()
{
    return "1234";
}

void CMyDLLApp::OnCalculate()
{
    int lastCode = info.No + 111;
    testCallBack(lastCode);
}

void CMyDLLApp::DoTest()
{
    char buf[256] = {0};
    sprintf_s(buf, "the result is %s and %s", info.name, info.content);
    resultCallBack(buf);
}
  • MyDLL.def文件 因为导出整个类,这边可以不用声明
代码语言:javascript
复制
; MyDLL.def : 声明 DLL 的模块参数。

LIBRARY  

EXPORTS
    ; 此处可以是显式导出
  • 最后编译生成lib和dll文件

新建MFC调用客户端项目
  • 这边是新建对话框的项目

  • 在新建项目下,建立一个目录这边是libDll,在改目录下分别建立inc和lib目录

然后将MyDLL.h头文件拷贝到inc目录,将dll项目生成的MyDLL.dll和MyDLL.lib两个文件拷贝到lib下

  • 然后进行配置,项目属性-->链接器 -->常规,配置附加库目录,这边是配置外来库的文件目录(libDLL/lib 将外来库文件放置这)

  • 接着配置lib目录,项目属性-->C++ -->常规,配置附加包含目录,这边是配置外来附加头文件目录

然后再配置库名称,项目属性->链接器-->输入,配置附加依赖项,即把要添加的lib,名称加进去

到此依赖的静态链接库都配置好了。

  • 引用 MFCTestDLLDlg.h 引入依赖的库和对应的头文件#include "MyDLL.h" #pragma comment(lib, "MyDLL.lib")
代码语言:javascript
复制
// MFCTestDLLDlg.h : 头文件
#pragma once
#include "MyDLL.h"
#pragma comment(lib, "MyDLL.lib")

// CMFCTestDLLDlg 对话框
class CMFCTestDLLDlg : public CDialogEx
{
// 构造
public:
    CMFCTestDLLDlg(CWnd* pParent = NULL);   // 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MFCTESTDLL_DIALOG };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
    HICON m_hIcon;

    // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedButton1();
    CMyDLLApp MyDllApp;
    afx_msg void OnBnClickedButton2();
        //因为静态的方法无法使用非静态的成员,所以更新UI,采用消息发送的形式
    afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
        //两个回调传递的方法必须是静态的,否则会报错
    static void TestCallback(int code);
    static void ResultCallBack(const char* result);
        CStatic m_static1;
       CStatic m_static2;
};

MFCTestDLLDlg.cpp

代码语言:javascript
复制
// MFCTestDLLDlg.cpp : 实现文件
#include "stdafx.h"
#include "MFCTestDLL.h"
#include "MFCTestDLLDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define WM_UI_MESSAGE WM_USER + 105


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFCTestDLLDlg 对话框


CMFCTestDLLDlg::CMFCTestDLLDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_MFCTESTDLL_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCTestDLLDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCTestDLLDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTON1, &CMFCTestDLLDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON2, &CMFCTestDLLDlg::OnBnClickedButton2)
    ON_MESSAGE(WM_UI_MESSAGE, OnMyMessage)
END_MESSAGE_MAP()

//消息接收方法
LRESULT CMFCTestDLLDlg::OnMyMessage(WPARAM wParam, LPARAM lParam) {
    if (wParam == 0)
    {
        CString* result = (CString*)lParam;
        MessageBox(result->GetBuffer(), MB_OK);
    }
    return 0;
}


// CMFCTestDLLDlg 消息处理程序

BOOL CMFCTestDLLDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);         // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    // TODO: 在此添加额外的初始化代码
    TestInfo info;
    info.No = 100;
    info.name ="jack";
    info.content = "this is test dll";
    MyDllApp.InitTest(info, "8888");

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMFCTestDLLDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFCTestDLLDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCTestDLLDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

void CMFCTestDLLDlg::OnBnClickedButton1()
{
    MyDllApp.SetTestCallBack(TestCallback);

}

void CMFCTestDLLDlg::OnBnClickedButton2()
{
    MyDllApp.SetResultCallBack(ResultCallBack);
}

void CMFCTestDLLDlg::TestCallback(int code)
{
    CString *codeCs = new CString();
    codeCs->Format(L"get the code is %d",code);
    ::PostMessage(AfxGetApp()->m_pMainWnd->m_hWnd, WM_UI_MESSAGE, NULL, (LPARAM)(codeCs));
}
void CMFCTestDLLDlg::ResultCallBack(const char * result)
{
    CString *codeCs = new CString();
    codeCs->Format(L"get the code is %s", result);
    ::PostMessage(AfxGetApp()->m_pMainWnd->m_hWnd, WM_UI_MESSAGE, NULL, (LPARAM)(codeCs));
}

到此整个项目over了,但是还存在几个问题,一个是字符串回传的时候,会出现乱码;一个是编译会提示警告出现宏重定义。

参考: https://www.cnblogs.com/19910101zj/p/4611695.html http://www.jb51.net/article/56602.htm http://blog.csdn.net/tajon1226/article/details/55190247

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简语:
  • 开发环境
  • 开发语言
  • 开发步骤
  • 构建MFC的DLL项目
  • 新建MFC调用客户端项目
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档