从导入的DLL中调用主程序中的函数

时间:2019-06-06 06:55:50

标签: c++ plugins dllexport

我正在尝试创建一个使用C ++插件的程序,以获取有关从.dll和.so库导入和导出函数的一些经验。为了简单起见,我们仅在这里使用.dll库。

我要做的是使插件与加载了它的主程序之间的通信“双向”,这意味着主程序可以从插件调用函数(此问题已解决),并且插件应能够从主程序调用函数(对此我遇到了麻烦)。

我目前能够创建一个.dll,并在其中使用 extern“ C” {} __ declspec(export)导出函数。

TestPlugin.h

#pragma once

extern "C" {
    __declspec(dllexport) const char* pluginName();
    __declspec(dllexport) void onLoad();
    __declspec(dllexport) void onShutdown();
}

TestPlugin.cpp

#include "TestPlugin.h"

#include <iostream>

const char * pluginName()
{
    return "Test Plugin";
}

void onLoad()
{
    std::cout << "onLoad() called!" << std::endl;
}

void onShutdown()
{
    std::cout << "onShutdown() called!" << std::endl;
}

然后,我使用以下(缩短的)代码加载此测试插件。我删除了错误检查和控制台输出。

Plugin.h

#pragma once

#include <filesystem>
#include <iostream>
#include <windows.h>

class Plugin
{
private:
    typedef const char*(*pluginNameType)();
    typedef void(*onLoadType)();
    typedef void(*onShutdownType)();

    HINSTANCE m_lib;
public:
    Plugin(std::filesystem::path filename);
    ~Plugin();

    pluginNameType pluginName;
    onLoadType onLoad;
    onShutdownType onShutdown;
};

Plugin.cpp

#include "Plugin.h"

Plugin::Plugin(std::filesystem::path filename)
{
    m_lib = LoadLibrary(filename.wstring().c_str());

    pluginName = (pluginNameType)GetProcAddress(m_lib, "pluginName");
    onLoad = (onLoadType)GetProcAddress(m_lib, "onLoad");
    onShutdown = (onShutdownType)GetProcAddress(m_lib, "onShutdown");
}

Plugin::~Plugin()
{
    FreeLibrary(m_lib);
}

我现在能做的是从主程序调用插件(TestPlugin.cpp)中的函数。

main.cpp

Plugin *plugin = new Plugin("pathToDLLGoesHere");
plugin->onLoad();
plugin->onShutdown();

我现在想做的是还使我刚刚加载的测试插件能够访问主程序中定义的功能。所以说在我的main.cpp中,我有这样的东西...

main.cpp

int testCall(int val) {
    return val + 1;
}

int main()
{
    ...

    return 0;
}

...如何从测试插件调用 testCall()

将功能指针发送到插件并使用它会如此简单吗?还是我需要在这里采取其他方法?谢谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我已经弄清楚了它是如何工作的。您还可以使用 extern“ C” {} __ declspec(dllexport)从主程序中导出函数,以便DLL可以看到它们以及何时获得句柄。 DLL中的主程序,可以调用这些函数。

在主程序的头文件之一中,导出函数。

main.h

extern "C" {
    __declspec(dllexport) int testCall(int val);
}

main.cpp

int testCall(int val) {
    return val + 1;
}

在测试插件头中,我为主程序创建了一个句柄,并为要从main调用的函数定义了一个

TestPlugin.h

#pragma once

#include <windows.h>

HINSTANCE app;
int(*testCall)(int val);

...

然后在主体中分配句柄(使用 nullptr 调用 GetModuleHandle 将为您提供程序的句柄),然后从主程序获取导出的函数

TestPlugin.cpp

app = GetModuleHandle(nullptr);
testCall = (int(*)(int val))GetProcAddress(app, "testCall");

之后,我可以调用该函数。

std::cout << testCall(5) << std::endl;

result