Visual Studio 如何将DLL链接到新项目?

ht4b089n  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(188)

Header.h

#pragma once
#include <string>

using namespace std;

#define DLLIMPORT __declspec(dllexport)

extern "C" {
    DLLIMPORT class Config {
    public:
        static string path;
        static string test;
        static void get_file();
    };
    DLLIMPORT Config* GetConfigInstance();
}

dllmain.cpp

#include "pch.h"
#include "Header.h"
#include <iostream>
#include <fstream>
#include <direct.h>

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}


string Config::path;
string Config::test;

void Config::get_file() {
    ifstream infile("cfg.txt");
    char cwd[1024];
    if (_getcwd(cwd, sizeof(cwd)) == nullptr) {
        std::cerr << "Failed to get current working directory" << std::endl;
    }

    std::cout << "Current working directory: " << cwd << std::endl;
    std::cout << "Reading file: " << cwd << "/cfg.txt" << std::endl;
    string line;
    while (getline(infile, line)) {
        size_t pos = line.find("=");
        string key = line.substr(0, pos);
        string val = line.substr(pos + 1);
        if (key == "img_path") {
            path = val;
        }
        else if (key == "test") {
            test = val;
        }
    }
}

Config* GetConfigInstance()
{
    return new Config();
}

main.cpp

#include <iostream>
#include <windows.h>
#include "Header.h"

int main() {
    HINSTANCE hinstLib = LoadLibrary(TEXT("Util_aoi_model.dll"));
    if (hinstLib == NULL) {
        std::cerr << "Failed to load DLL" << std::endl;
        return 1;
    }

    typedef Config* (*GetConfigInstanceFunction)();
    GetConfigInstanceFunction getConfigInstance = (GetConfigInstanceFunction)GetProcAddress(hinstLib, "GetConfigInstance");
    if (getConfigInstance == NULL) {
        std::cerr << "Failed to get address of GetConfigInstance function" << std::endl;
        return 1;
    }

    Config* config = getConfigInstance();
    config->get_file();
    std::cout << "img_path: " << Config::path << std::endl;
    std::cout << "test: " << Config::test << std::endl;

    FreeLibrary(hinstLib);

    return 0;
}

我一直在构建.dll.lib,但是当我使用另一个.sln调用它们时,它会显示错误:
未解外部符号
我确定我添加了include路径和lib路径。
链接输入具有.lib的名称。
谁能帮我解决这个错误?
header.hdllmain.cpp文件在同一个项目中,并构建了.dll.lib
另一个main.cpp在一个新项目中,我正在尝试使用DLL函数get_file()

46scxncf

46scxncf1#

在第二种解决方案中,编译器正在寻找get_file()的实现,它将无法访问。此外,您不能跨DLL边界使用std::string等非平凡类型。
您需要从Config中删除所有数据成员,并使其所有方法都成为非静态纯虚方法。换句话说,使Config成为抽象接口。然后让DLL使用单独的类实现该接口,然后可以示例化并返回指针。
试试这个:
Header.h

#pragma once

#ifdef BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif

extern "C" {

class Config {
public:
    virtual const char* get_path() = 0;
    virtual const char* get_test() = 0;
    virtual void get_file() = 0;
};

DLLIMPORT Config* GetConfigInstance();

}

dllmain.cpp

#include "pch.h"

#define BUILDING_DLL
#include "Header.h"

#include <iostream>
#include <fstream>
#include <string>
#include <direct.h>

using namespace std;

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

class ConfigImpl : public Config {
public:
    string path;
    string test;
    const char* get_path() override;
    const char* get_test() override;
    void get_file() override;
};

const char* ConfigImpl::get_path() {
    return path.c_str();
}

const char* ConfigImpl::get_test() {
    return test.c_str();
}

void ConfigImpl::get_file() {
    ifstream infile("cfg.txt");
    char cwd[1024];
    if (_getcwd(cwd, sizeof(cwd)) == nullptr) {
        cerr << "Failed to get current working directory" << endl;
    }

    cout << "Current working directory: " << cwd << endl;
    cout << "Reading file: " << cwd << "/cfg.txt" << endl;
    string line;
    while (getline(infile, line)) {
        size_t pos = line.find("=");
        string key = line.substr(0, pos);
        string val = line.substr(pos + 1);
        if (key == "img_path") {
            path = val;
        }
        else if (key == "test") {
            test = val;
        }
    }
}

Config* GetConfigInstance()
{
    static ConfigImpl impl;
    return &impl;
}

main.cpp

#include <iostream>
#include <windows.h>
#include "Header.h"

int main() {
    HINSTANCE hinstLib = LoadLibrary(TEXT("Util_aoi_model.dll"));
    if (hinstLib == NULL) {
        std::cerr << "Failed to load DLL" << std::endl;
        return 1;
    }

    typedef Config* (*GetConfigInstanceFunction)();
    GetConfigInstanceFunction getConfigInstance = (GetConfigInstanceFunction)GetProcAddress(hinstLib, "GetConfigInstance");
    if (getConfigInstance == NULL) {
        std::cerr << "Failed to get address of GetConfigInstance function" << std::endl;
        return 1;
    }

    Config* config = getConfigInstance();
    config->get_file();
    std::cout << "img_path: " << config->get_path() << std::endl;
    std::cout << "test: " << config->get_test() << std::endl;

    FreeLibrary(hinstLib);

    return 0;
}

相关问题