Deje que un dll llame a una función .exe enviando un puntero [duplicado]

Esta pregunta se parece a una que hice antes, excepto que ahora sé que no se puede llamar a la función principal desde un objeto global. Entonces este código no funciona con main. Pero, ¿por qué falla también con otras funciones?

Este es el código.

.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
clase_dll.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;
};

plataforma.h

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

plataforma.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);
}

Funciona muy bien, hasta cierto momento. Esta es la salida.

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

pero nunca dice:

Enter the my_main code.
Enter the main code.

¿Es imposible dejar que dll llame a una función exe?

preguntado el 09 de marzo de 13 a las 14:03

Creo que su problema tiene menos que ver con un puntero a la función en el EXE y más con hilos. También puede tener violaciones de la regla de una definición. ¿La aplicación y la biblioteca utilizan las mismas opciones de compilación? -

Dónde está main_p declarado en tu Platform ¿clase? -

@Tony: Mostró ese código, es global en plataforma.cpp -

@BenVoigt Lo pasé por alto. Lo siento -

Definitivamente agregaría un std::endl; or std::flush a la salida, ya que si el subproceso no hace eso, es posible que nunca emita la salida real. -

2 Respuestas

La respuesta sigue siendo la misma que le di a su otra pregunta. Su Platform el constructor está colgado. Las condiciones de finalización del ciclo nunca se cumplen, por lo que el constructor nunca regresa. Y el main La función no puede ejecutarse hasta que se hayan construido todos los objetos globales.

Noticias: La discusión anterior fue por qué Enter the main code nunca imprime.

Si pasas por tu my_main función, verá el problema con Enter the my_main code: Las llamadas a cout y getchar son ignorados. Esto se debe a que no se especifica el orden de las construcciones de objetos globales en diferentes unidades de traducción. En el ejecutable principal, el object el objeto global se está construyendo primero, lo que significa que el cin y cout los objetos pueden no estar completamente construidos. Es por eso cout no puedo imprimir y porque getchar no puedo leer.

respondido 09 mar '13, 16:03

Entonces como se imprime Calling the main function ? - neel basu

@Raymond Chen: he enviado la función my_main como puntero. La función principal en la parte inferior de main.cpp no ​​se usa esta vez. - JMRC

@Raymond Chen: Pero el punto de interrupción tampoco se activa. Debería activarse, ¿no? Y sin un desmontaje estoy completamente despistado. - JMRC

Luego paso por el callMain función. Tenga en cuenta que incluso si logra que esto "funcione", está confiando en un comportamiento no especificado, por lo que no es un buen plan. - Raymond Chen

@Raymond Chen: Tengo un comentario anterior que dice lo que sucede cuando hago eso. Pero también creo que debería buscar una alternativa. No creo que sea capaz de resolver esto. - JMRC

Seguramente, lo CORRECTO que se debe hacer aquí es construir el object dentro main. Si es necesario, pase my_main al objeto Pero esto resolverá todos los "intentos de usar algo antes de que se haya construido".

La clave aquí (que solo deduzco al leer los comentarios sobre la otra respuesta) es que el cout el objeto no es "el mismo" para el ejecutable principal y la DLL. Esto conduce a problemas con las cosas que no llaman cout antes de que hayas entrado main [que también traté de explicar en la pregunta anterior: la biblioteca de tiempo de ejecución de C necesita inicializar ciertas cosas, y eso sucede en un orden no especificado antes main se llama].

respondido 09 mar '13, 17:03

Pensé que solo te referías al principal en sí, no a otros objetos. Inicializar el objeto en main Era el plan B, pero iba en contra de las pautas que quería usar. Pero no se puede tener todo, supongo. - JMRC

En Windows, si vincula sin usar DLL, obtiene múltiples copias de globales. Si vincula todo usando DLL, entonces no debería hacerlo. En MSVC, la opción está en las propiedades del proyecto/C/C++/Code Generation/Runtime Library. - Brian Beuning

Ya estaba en /MDd. - JMRC

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.