【问题标题】:Let a dll call a .exe function by sending a pointer [duplicate]通过发送指针让dll调用.exe函数[重复]
【发布时间】:2013-03-09 14:43:05
【问题描述】:

这个问题看起来像我之前问过的问题,除了我现在知道你不能从全局对象调用 main 函数。所以这段代码不适用于main。但是为什么其他功能也会失败呢?

这是代码。

.exe
main.cpp

#include "dll_class.h"
#include <iostream>
int my_main(void)
{
    std::cout << "Enter the my_main code.\n";
    std::getchar();
}

DllClass object(my_main);
int main(void)
{
    std::cout << "Enter the main code.\n";
    std::getchar();
}

.dll
dll_class.h

#include "platform.h"
#include <iostream>
class DLL_API DllClass //DLL_API is just a macro for import and export.
{
public:
    DllClass(int(*main)(void))
    {
        std::cout << "Start application.\n";
        platform = new Platform(main);
    }
    ~DllClass(void)
    {
        delete platform;
    }
private:
    Platform* platform;
};

平台.h

class DLL_API Platform
{
public:
    Platform(main_t main_tp);
    ~Platform(void){}
};

平台.cpp

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

HHOOK hookHandle;
int(*main_p)(void);//This will hold a the main function of the the .exe.
LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam);

DWORD WINAPI callMain(_In_  LPVOID lpParameter)
{
    std::cout << "Calling the main function.\n";
    main_p();
    return 0;
}

Platform::Platform(int(*main_tp)(void))
{
    main_p = main_tp;
    CreateThread(NULL, 0, callMain, NULL, 0, NULL);
    std::cout << "Setting hooks.\n";
    hookHandle = SetWindowsHookEx(WH_MOUSE_LL, keyHandler, NULL, 0);
    std::cout << "Enter message loop.\n";
    MSG message;
    while(GetMessage(&message, (HWND)-1, 0, 0) != 0){
        TranslateMessage( &message );
        DispatchMessage( &message );
    }
}

LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
    std::cout << "Inside the hook function.\n" << std::endl;
    return CallNextHookEx(hookHandle, nCode, wParam, lParam);
}

它运行得很好,直到某个时刻。 这是输出。

Start application.  
Setting hooks.  
Calling the main function.  
Enter message loop.  
Inside the hook function. (A lot of times of course).  

但它从来没有说:

Enter the my_main code.
Enter the main code.

难道不能让dll调用exe函数吗?

【问题讨论】:

  • 我认为您的问题与指向 EXE 中函数的指针关系不大,而与线程有关。您可能还违反了单一定义规则。应用程序和库是否使用相同的编译选项?
  • main_p 在你的 Platform 类中声明在哪里?
  • @Tony:他展示了那个代码,它是platform.cpp中的一个全局
  • @BenVoigt 我忽略了它。对不起
  • 我肯定会在输出中添加std::endl;std::flush,因为如果线程不这样做,它可能永远不会输出实际输出。

标签: c++ multithreading winapi dll


【解决方案1】:

答案仍然与我对您其他问题的答案相同。您的 Platform 构造函数已挂起。循环终止条件永远不会满足,因此构造函数永远不会返回。并且 main 函数在所有全局对象构建完成之前无法运行。

更新:上面的讨论是为什么Enter the main code 从不打印。

如果您单步执行您的my_main 函数,您将看到Enter the my_main code 的问题:对coutgetchar 的调用被忽略。这是因为不同翻译单元中全局对象的构造顺序是未指定的。在主可执行文件中,首先构造了object 全局对象,这意味着cincout 对象可能没有完全构造。这就是cout 无法打印以及getchar 无法读取的原因。

【讨论】:

  • 那么如何打印Calling the main function ?
  • @Raymond Chen:我已将 my_main 函数作为指针发送。 main.cpp底部的main函数这次不用了。
  • @Raymond Chen:但是断点也没有被触发。它应该被触发,不是吗?如果没有拆卸,我完全一无所知。
  • 然后单步执行callMain 函数。请注意,即使你让它“工作”,你也依赖于未指定的行为,所以这不是一个好计划。
  • @Raymond Chen:我在上面有一条评论说当我这样做时会发生什么。但我也认为我应该寻找替代方案。我不认为我能够解决这个问题。
【解决方案2】:

当然,正确的做法是在main 中构造object。如果需要,将my_main 传递给对象。但这将解决所有“在构建之前尝试使用某些东西”。

这里的关键(我只是通过阅读另一个答案的 cmets 收集到的)是 cout 对象对于主可执行文件和 DLL 不是“同一个”。这会导致在您输入main 之前调用cout 的事情[我也试图在上一个问题中解释-C 运行时库需要初始化某些事情,并且在@ 之前以未指定的顺序发生987654327@ 被调用]。

【讨论】:

  • 我以为你只指主要本身,而不是其他对象。初始化 main 中的对象是 B 计划,但这违背了我想要使用的准则。但你不可能拥有我猜想的一切。
  • 在 Windows 上,如果您在不使用 DLL 的情况下进行链接,那么您将获得多个全局变量副本。如果您使用 DLL 链接所有内容,那么您不应该这样做。在 MSVC 中,该选项位于项目属性/C/C++/代码生成/运行时库中。
  • 它已经在 /MDd 上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 2013-02-16
  • 1970-01-01
相关资源
最近更新 更多