I have shared library that is compiled from C++ code, and want to use it from nim. I can dynlib import function names (using their mangled variant), but library is also defines a macro that generates calls to the functions, and when code is compiled it fails with "undefined reference to <XXX>". Here is a simplified example of the library
name.hpp
namespace Optick {
struct FrameType { enum Type { CPU, GPU }; };
namespace Core { void BeginFrame(FrameType::Type, long, unsigned long); }
}
void BeginFrameSimple();
#define AUX BeginFrameSimple(); Optick::Core::BeginFrame(Optick::FrameType::CPU, 0, 0);
name.cpp
#include "name.hpp"
#include <iostream>
namespace Optick {
namespace Core { void BeginUpdateFrame(FrameType::Type, long, unsigned long) {
std::cout << "Called namespaced\n";
} }
}
void BeginFrameSimple() { std::cout << "Called standalone\n"; }
Compiled with gcc name.cpp -fpic -shared -olibname.so
Using it from nim is not entirely straightforward (I had to dump .so file to figure out correct symbol names, but I guess that's just how I have to do things because of C++ being involved). Nim code -
nimfile.nim
const
so = "./libname.so"
h = "name.hpp"
const simple = false
type
FrameTypeType {.importcpp: "Optick::FrameType::Type", header: h.} = enum
ftCpu
ftGpu
# ...
proc BeginFrame(): uint32 {.dynlib: so, cdecl, importc: "_Z16BeginFrameSimplev".}
discard BeginFrame()
proc BeginFrame(
ftype: FrameTypeType,
timestamp: uint64,
threadID: uint64
): uint32 {.
dynlib: so,
cdecl,
importc: "_ZN6Optick4Core16BeginUpdateFrameENS_9FrameType4TypeElm".}
discard BeginFrame(ftCPU, 0, 0)
Correctly creates expected output, no issues there.
Called standalone
Called namespaced
But when I try to do
proc aux() {.importc: "AUX", header: h.}
aux()
it (expectedly) fails with
@mnimfile.nim.cpp:(.text+0x247): undefined reference to `BeginFrameSimple()'
/bin/ld: @mnimfile.nim.cpp:(.text+0x25b): undefined reference to `Optick::Core::BeginFrame(Optick::FrameType::Type, long, unsigned long)'
What should I do in cases like these?
Real world use case is OPTICK_FRAME macro https://github.com/bombomby/optick/blob/master/src/optick.h#L854 that calls into https://github.com/bombomby/optick/blob/master/src/optick.h#L472 BeginFrame which itself is placed in the dynamic library.