У меня есть решение с 3 проектами:
Export.h
#pragma once
#ifdef DLL_EXPORT
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
Lib1.h
#pragma once
#include "Export.h"
class Member { };
class EXPORT Base {
public:
static Member* GetStaticMember();
virtual void SetMember(Member* member) = 0;
protected:
static Member* m_member;
};
class Worker {
public:
void DoSomething();
};
Lib1.cpp
#include "pch.h"#include "Lib1.h"
Member* Base::m_member;
Member* Base::GetStaticMember() {
return m_member;
}
void Worker::DoSomething() {
Member* test = Base::GetStaticMember(); // RETURNS 0
}
Dll1.h
#pragma once
#include "Lib1.h"#include "Export.h"
class EXPORT ChildA : public Base {
public:
virtual void SetMember(Member* member) override;
};
Dll1.cpp
#include "pch.h"#include "Dll1.h"
void ChildA::SetMember(Member* member) {
Base::m_member = member;
Member* test = Base::GetStaticMember(); // RETURNS CORRECT ADDRESS
}
Member* member = new Member();
ChildA* childa = new ChildA();
childa->SetMember(member); // Base::GetStaticMember() inside this RETURNS CORRECT ADDRESS
Worker* worker = new Worker();
worker->DoSomething(); // Base::GetStaticMember() inside this RETURNS 0
При прохождении в отладчике Base :: GetStaticMember () возвращает правильный адрес члену после того, как он установлен (но все еще внутри childa-> SetMember (). Как только OUTSIDE childa, Base :: GetStaticMember () возвращает 0. Когда внутри worker-> DoSomething (), Base :: GetStaticMember () также возвращает 0. Может кто-нибудь объяснить мне, в чем причина и как это исправить, чтобы получить доступ к Base :: GetStaticMember () либо снаружи, либо внутри методов из dll или lib вернет правильный адрес а не 0?
Если вы используете статическую библиотеку, связанную с несколькими DLL и / или вашим EXE, каждая из них получит свою своя статическая переменная-член. Подумайте о механике того, как происходит * фаза связи каждого из них, и вы поймете, почему.
Вы Можно превратите ваши статические переменные в указатели, ссылающиеся на разделяемую память, поддерживаемую файлом с отображенной памятью, но я предупреждаю вас, что управлять им становится сложно. Я сделал это, поддерживая временный файл карты памяти, используя имя класса + member + pid в качестве имени отображения (примечание: pid должен был позволить нескольким процессам запускаться без надавливания друг на друга совместно используемой mem). это сработало на удивление хорошо.
Вы должны связать lib1
только с Dll1
или с App1
, не оба.
Теперь у вас есть Base::_member
определенный и то и другое в вашем Dll1
а также App1
,
Как вы определили Base
учебный класс __dllexport
/__dllimport
, оно использует Dll1
статический член, но вы не объявлены Worker
с любыми атрибутами, и он использует местный статический член.
Я полагаю, вы должны указать атрибуты для Worker
и не связывать App1
с Lib1