2015-07-28 3 views
1

Немного фона; Я пишу систему плагинов для игрового движка, в которой будет работать основной код двигателя, выполняемый exe (предоставляется библиотекой, например engine.lib). Я хочу иметь возможность экспортировать некоторые глобальные переменные из engine.lib в dll плагина, который загружается во время выполнения.Импорт переменных в DLL

Так, например;

engine.lib: Имеет переменную под названием g_foobar, который инициализируется в какой-то момент по ехе, что статически ссылки на engine.lib

plugin.dll: Это также статически ссылки на engine.lib, как Я хочу, чтобы иметь возможность манипулировать g_foobar, используя различные классы в engine.lib

Очевидно, когда плагин загружает его имеет собственный экземпляр g_foobar, не инициированные к тому же, как g_foobar в exe.

Я хочу (с небольшим количеством dllexport/магии DllImport) сделать ссылку динамического компоновщика до двух символов, так что g_foobar внутри DLL указывает на ту же память, что и один в ехе.

код, который я имел игру с (3-х проектов VS, EXE, enginelib, plugindll):

header.h

#pragma once 

#if !defined(__ISALIB__) 
    #if defined(__ISADLL__) 
     #define API __declspec(dllimport) 
    #else 
     #define API __declspec(dllexport) 
    #endif 
#else 
    #define API 
#endif 

class API CFoobar 
{ 
public: 
    CFoobar(int i); 
    int m_iDave; 
}; 

extern API CFoobar* g_foobar; 

EXE.cpp

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

typedef void (*FooFN)(); 

CFoobar s_Foo(100); 

int main(int argc, char** argv) 
{ 
    g_foobar = &s_Foo; 

    HMODULE h = LoadLibraryA("plugin.dll"); 

    FooFN func = (FooFN)GetProcAddress(h, "Foobar"); 

    func(); 

    return 0; 
} 

plugindll.cpp

#include "Header.h" 

extern "C" __declspec(dllexport) void Foobar() 
{ 
    printf("VALUE: %d\n", g_foobar->m_iDave); 
} 

enginelib.cpp

#include "Header.h" 

CFoobar* g_foobar = NULL; 

CFoobar::CFoobar(int i) 
    :m_iDave(i) 
{ 
} 

Даже после компиляции EXE/Lib/длл различными способами (изменение API определения), я не могу получить вывод на печать '100', он всегда будет печатать '0', потому что я статически связываюсь с engine.lib.

Мне интересно, знает ли кто-нибудь, как это работает, потому что есть что-то очевидное, что я делаю неправильно.

ПРИМЕЧАНИЕ. Удаление использования статической библиотеки на самом деле не является вариантом из-за того, как работает остальная часть кодовой базы.

Cheers.

+0

У вашего EXE есть своя копия g_foobar, связанная с enginelib. Без обмена. Необходимость использования LoadLibrary() делает его недружественным, вам нужно экспортировать функцию SetFooBar(), чтобы EXE мог установить указатель, используемый DLL. –

+0

Да, я понимаю, что есть две копии переменной, но я ищу для динамического компоновщика, чтобы g_foobar в dll указывал на то же пространство памяти, что и g_foobar в хосте exe, поэтому я могу получить доступ к любому это приложение для хоста. – Olly

+0

Ну, конечно, было бы проще, если бы вы дали динамически ссылку. Но вы этого не делаете и используете LoadLibrary(). Затем вам нужно связать себя с GetProcAddress(), вы уже знаете, как это сделать. Вы не можете иметь это в обоих направлениях, такова цена плагинов. –

ответ

0

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

Так основано на моем примере кода выше, enginelib становится DLL, и блок заголовка API становится:

#if defined(__ISADLL__) 
    #define API __declspec(dllexport) 
#else 
    #define API __declspec(dllimport) 
#endif 

И plugindll и Exe как ссылку на .lib создаваемого длл enginelib сборки.