Lua: модули С++ не могут ссылаться друг на друга, неопределенный символ

Я создал два модуля (общие объекты) CPU и SaveState как часть эмулятора. Оба независимо скомпилированы в отдельные файлы .so и загружены во время выполнения сценарием Lua с использованием require(); то есть:

SaveState = require("SaveState")
CPU = require("CPU")

Внутри CPU есть метод, который работает с SaveState:

int CPU::save_state(SaveState *state) {
    state->begin_section(savestate_namespace, savestate_data_size);

    state->write16(this->reg.af);
    state->write16(this->reg.bc);
    state->write16(this->reg.de);
    state->write16(this->reg.hl);
    state->write16(this->reg.sp);
    state->write16(this->reg.pc);
    state->write8 (this->interrupts_enabled);
    state->write8 (this->irq_flags);
    state->write8 (this->ie_flags);
    state->write8 (this->halted);
    state->write8 (this->halt_bug);
    state->write8 (this->extra_cycles);
    state->write64(this->total_cycles);
    state->write64(this->idle_cycles);

    return SaveState::OK;
}

Компилируется нормально, но строка require("CPU") не работает:

lua5.1: error loading module 'cpu' from file './src/cpu/build/cpu.so':
    ./src/cpu/build/cpu.so: undefined symbol: _ZN9SaveState7write64Ey

Используя nm -D, я вижу этот точный символ в savestate.so, но во время выполнения он почему-то не виден.


person Rena    schedule 30.01.2013    source источник
comment
Почему нельзя объединить оба модуля в один?   -  person Basile Starynkevitch    schedule 31.01.2013
comment
Это совершенно отдельные объекты, и SaveState также используется многими другими модулями программы, которые, вероятно, будут иметь одну и ту же проблему.   -  person Rena    schedule 31.01.2013
comment
Вы можете попробовать package.loadliblua.org/manual/5.2 /manual.html#pdf-package.loadlib›; особенно его * форма.   -  person lhf    schedule 31.01.2013
comment
Похоже, это именно то, что мне нужно, за исключением того, что это доступно только в 5.2, тогда как я использую 5.1. В нем есть package.loadlib, но не поддерживается параметр *. Я пытался просто указать имя функции и отбросить его: package.loadlib("src/savestate/build/savestate.so", "luaopen_savestate") (и аналогично для ЦП), а также просто использовать * в любом случае (иногда в одной версии Lua есть функция, которая не документирована до руководства следующей версии), но это не так. ничего не делать.   -  person Rena    schedule 31.01.2013
comment
Подозревается, что SaveState::write64 невозможно найти, тогда как другие варианты могут. Несоответствие версий? Старая версия, которая не поддерживает 64-битную?   -  person Lightness Races in Orbit    schedule 31.01.2013


Ответы (1)


Мне удалось решить эту проблему, написав третий модуль, который загружается раньше двух других и просто вызывает dlopen() в своем методе luaopen_module:

void *res = dlopen("src/savestate/build/savestate.so",
    RTLD_NOW | RTLD_GLOBAL);

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

person Rena    schedule 31.01.2013