如何导出静态链接到 MFC 的常规 MFC DLL 的函数,以便在 C++ 中与非 MFC Win32 控制台应用程序一起使用

How to export a function of a regular MFC DLL that is statically linked to MFC to use with a non MFC Win32 Console App in C++

我对 C++ 世界和这类任务还很陌生。 我很难解决这个问题。 如有任何帮助,我们将不胜感激!

我创建了一个静态链接到 MFC 的常规 MFC DLL。 (这是我第一次创建MFC项目)

MFC DLL 头文件内容

// Serial.h

#pragma once

#ifndef __AFXWIN_H__
    #error "include 'pch.h' before including this file for PCH"
#endif

#include "resource.h"       // main symbols

class SerialApp : public CWinApp
{
public:
    SerialApp();
    __declspec(dllexport) void __cdecl SerialApp::Init();

public:
    virtual BOOL InitInstance();
    DECLARE_MESSAGE_MAP()
};

MFC DLL 定义文件内容

// Serial.cpp

#pragma once
#include "pch.h"
#include "framework.h"
#include "Serial.h"
#include <iostream>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

BEGIN_MESSAGE_MAP(SerialApp, CWinApp)
END_MESSAGE_MAP()

SerialApp::SerialApp()
{
}

SerialApp theApp;

BOOL SerialApp::InitInstance()
{
    CWinApp::InitInstance();
    return TRUE;
}

extern "C" 
{
    __declspec(dllexport) void __cdecl SerialApp::Init()
    {
        AfxDebugBreak();
        std::cout << "Succeded";
    }
}

Win32 控制台应用程序内容

#include <iostream>
#include <Windows.h>

int main()
{   
    //Load the DLL
    HMODULE lib = LoadLibrary(L"D:\C++ PROJECTS\serial\Debug\Serial.dll");

    //Create the function
    typedef void(*Init_t)(void);
    Init_t Serial = (Init_t)GetProcAddress(lib, "Init");
    std::cout << GetLastError(); // This output's 127

    if (!Serial) {
        //ERROR.  Handle it.
    }

    __declspec(dllimport) void __cdecl Init(void);
    //Init(); //LNK2019 unresolved external symbol "__declspec(dllimport) void __cdecl Init(void)"

    std::getchar();
}

当我使用这种方法时:

 __declspec(dllimport) void __cdecl Init(void);
 Init();

//I am getting the linker error LNK2019 unresolved external symbol "__declspec(dllimport) void __cdecl Init(void)"

当我使用这种方法时:

typedef void(*Init_t)(void);

Init_t Serial = (Init_t)GetProcAddress(lib, "Init");
std::cout << GetLastError();

//I am getting error code 127 from the GetLastError() function. (The specified procedure could not be found)

当我使用这种方法时:

#include "Serial.h"

int main()
{   
    SerialApp pSerial;
    pSerial.Init();
    std::getchar();
}

//Serial.h forces me to include 'pch.h' before itself. if i include 'pch.h' into Win32 Console App before Serial.h It end's up with about 1000's of errors.

对于 Win32 控制台应用程序项目:

1. C/C++ -> General -> Additional Include Directories is set to: D:\C++ PROJECTS\serial\Serial

2. Linker -> Input -> Additional Dependencies is set to : Serial.lib

3. Both Serial.lib and Serial.dll are included in the project and in the Debug folder.

4. Both MFC Dll Project and Win32 Console Projects are compiled in Debug x86 mode.

问题

  1. What i am doing wrong?
  2. Is this even possible?

谢谢!

问题由@dxiv的评论解决:

You cannot import a member function like SerialApp::Init to a non-MFC app, because that app does not know about the SerialApp class, and cannot know about it since SerialApp is derived from CWinApp which is an MFC class, while your app is non-MFC. If you want to export a free function from the DLL, then make it __declspec(dllexport) void __cdecl Init(void); outside the SerialApp class, or any class for that matter.

1. 我从头文件中删除了声明__declspec(dllexport) void __cdecl SerialApp::Init();

2. Rewrite the definition of Init() in the Serial.cpp file as:

extern "C" 
{
    __declspec(dllexport) void __cdecl Init()
    {
        std::cout << "Succeded";
    }
}

3. I call the function in Win32 Console App as:

int main()
{
    //Load the DLL
    HMODULE lib = LoadLibrary(L"D:\C++ PROJECTS\serial\Debug\Serial.dll");

    //Create the function
    typedef void(*Init_t)(void); // <- You can name Init_t whatever you want.
    Init_t Serial = (Init_t)GetProcAddress(lib, "Init");

    if (!Serial) {
        std::cout << GetLastError();
        return 1;
    }

    Serial();   //<- Init() Function Call from Serial.dll
    
    std::getchar();
    return 0;
}

一切都很好!

谢谢大家抽出时间阅读并回答我的问题!