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

1

6

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.

Reinsure answered 30/1, 2013 at 23:45 Comment(5)
Why can't you merge both modules into a single one?Lozengy
They're completely separate objects, and SaveState is used by many other modules in the program as well, that will probably all have the same problem.Reinsure
You may want to try package.loadlib <lua.org/manual/5.2/manual.html#pdf-package.loadlib>; especially its * form.Gabler
That looks like exactly what I need, except it's only available in 5.2, whereas I'm using 5.1. That has package.loadlib, but doesn't support the * option. I tried just providing a function name and discarding it: package.loadlib("src/savestate/build/savestate.so", "luaopen_savestate") (and likewise for CPU), as well as just using * anyway (sometimes one version of Lua has a feature that isn't documented until the next version's manual), but it didn't appear to do anything.Reinsure
It's suspect that SaveState::write64 cannot be found whereas the other variants can. Version mismatch? Older version that doesn't support 64-bit?Cordless
R
2

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...)

Reinsure answered 31/1, 2013 at 2:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.