2014-01-22 4 views
2

У меня есть приложение, которое использует DLL для расширения функциональности (модулей). Я хотел бы вставить некоторые конкретные функции из другой программы (которая является сервером).Запуск main() .exe в качестве части .dll

Другая программа имеет относительно простой n-main.cpp

#include <n.h> 

int main(int argc, char * argv[]) 
{ 
    // creates a listen server and blocks the main thread 
    // until it receives SIGKILL/SIGTERM or a custom HTTP header to stop 
    n::start(argc,argv); 
} 

Так что я сделал это:

#include <modulespecs.h> 
#include <mymodule.h> // only some general specs 
#include <n.h> // copied from n-main.cpp, no errors 

// The main program calls this function to attach the module 
void onModuleAttached(){ 

    // create some fake arguments 
    int argc = 2; 
    char * argv[] = {"n.exe","someconfig.js"}; 

    // and act as if 
    n::start(argc,argv); 
} 

Это отлично работает до сих пор, сервер создается, ждет входящих соединений, и отвечает на запросы должным образом.

Единственная проблема заключается в том, что при загрузке модуля сервер блокирует основное приложение, поэтому основное приложение не продолжает работать, поскольку оно ожидает, что сервер в моем модуле сначала завершит работу (чего не произойдет). И даже если это так, у сервера есть логика, чтобы полностью закрыть основное приложение, когда оно умирает.

Что я пробовал:

#include <thread> 

    void create_server(){ 
     int argc = 2; 
     char * argv[] = {"n.exe","someconfig.js"}; 

     // and act as if 
     n::start(argc,argv); 
    } 
    void onModuleAttached(){ 

     // crashes 
     std::thread test(create_server); 

     // creates the server, then exits immediately 
     std::thread (create_server).join(); 

     // same as join() 
     std::thread (create_server).detach(); 
    } 

Есть ли конкретный способ достижения этой цели?

ответ

3

Я предполагаю, что вы вызываете onModuleLoaded() из своей функции DllMain(). DllMain() вызывается во время блокировки загрузчика ОС, и поэтому вы должны never do anything scary inside DllMain(). Создание потоков - одна из таких страшных вещей, поэтому вы никогда не должны делать этого внутри DllMain().

Рекомендуемый способ избежать этого - иметь отдельную точку входа в DLL, которая делает страшную информацию, и вашей DLL, чтобы эта точка входа вызывалась после инициализации DLL. Также необходимо предоставить соответствующую процедуру выхода, которая должна быть выведена перед выгрузкой библиотеки DLL.

Например:

DLLEXPORT BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
{ 
    // Nothing much here 
} 

std::thread server_thread; 

DLLEXPORT void StartServer() 
{ 
    server_thread = std::thread(create_server); 
} 

DLLEXPORT void StopServer() 
{ 
    server_thread.join(); 
} 

Тогда ваша основная программа может выглядеть следующим образом:

// Load the DLL and get its entry and exit routines 
HMODULE serverDLL = LoadLibrary(...); 
void (*StartServer)() = (void (*)())GetProcAddress(serverDLL, "StartServer"); 
void (*StopServer)() = (void (*)())GetProcAddress(serverDLL, "StopServer"); 

// Call the entry routine to start the server on a new thread 
StartServer(); 

// Do other main program stuff 
// ... 

// We're done now, tell the server to stop 
StopServer(); 
FreeLibrary(serverDLL); 
+0

Это уже происходит. За исключением 'StartServer()' и 'StopServer()' вызывается для каждого модуля (включая мой), и на самом деле они называются 'onModuleAttached()' и 'onModuleDetached()'. Попытка этого подхода с помощью 'std :: thread', объявленного вне функций, приводит к выходу основного приложения. К сожалению. –

+0

Я попытался обобщить вопрос, чтобы соблюдать правила. Ваш ответ был правильным в данной ситуации, мне все равно пришлось изменить свой подход. Спасибо. –

Смежные вопросы