Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua: C++ modules can't reference eachother, undefined symbol

I've created two modules (shared objects) CPU and SaveState as part of an emulator. Both are independently compiled into .so separate files, and loaded at runtime by a Lua script using require(); i.e.:

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

Within CPU, there's a method that operates on a 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;
}

It compiles fine, but the require("CPU") line fails:

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

Using nm -D I can see that exact symbol in savestate.so, but at runtime it's not seen for some reason.

like image 701
Rena Avatar asked Jan 30 '13 23:01

Rena


1 Answers

I managed to solve this by writing a third module, which gets loaded before the other two and just calls dlopen() in its luaopen_module method:

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

I'm not sure this is the best solution, but it seems to do the trick. (I'll have to generalize it a bit to not use hardcoded paths and so on...)

like image 76
Rena Avatar answered Nov 17 '22 21:11

Rena