-
BackgroundIn my project, I need a mechanism to share a variable between the MAIN_MODULE and SIDE_MODULE. Additionally, the side module should access this variable during initialization. I discovered that if both modules are compiled with the USE_PTHREADS=1 flag, they share the same virtual memory. However, I am unable to pass the variable's address from the main module to the side module during its initialization. To work around this, I opted to use a constant memory address to store the address of the shared variable. When the main module starts, it sets the shared variable's address at this constant location. This allows the side module, upon loading, to read the constant address and access the shared variable. I'm curious if there is a more efficient or elegant solution to this problem? Reproduce demoHere is a demo to reproduce my way to solve the problem:
In b.cpp:
Use the following commands to compile them:
Using shared memory may need a HTTP server. Here is a simple way to setup it:
Use If everything works well, you should get the following output in console:
Version of emscripten/emsdk:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Can you share a reproducer for the code that doesn't work. You certainly don't want to be hard coding memory addresses in your code, that approach is extremely fragile. |
Beta Was this translation helpful? Give feedback.
-
you can try this way, passing the address to Module for proxy, using more cpp style, dude #include <dlfcn.h>
#include <iostream>
#include <map>
#include <stdio.h>
#include <string>
#include <emscripten.h>
typedef void (*func_t)();
static std::map<std::string, func_t> register_map;
int main()
{
printf("hello world,addr of `register_map`=%p\n",®ister_map);
// make sure using in the same thread
EM_ASM({
if(!Module["register_map"]) {
Module["register_map"] = $0;
}
}, ®ister_map);
std::cout << "before loading" << std::endl;
std::cout << register_map["hello"] << std::endl;
std::cout << register_map["world"] << std::endl;
void *handle = dlopen("b.so", RTLD_LAZY);
if (!handle)
{
std::cerr << dlerror() << std::endl;
return -1;
}
std::cout << "after loading" << std::endl;
std::cout << register_map["hello"] << std::endl;
std::cout << register_map["world"] << std::endl;
register_map["hello"]();
register_map["world"]();
}
// emcc -o b.so -s USE_PTHREADS=1 -sSIDE_MODULE -s INITIAL_MEMORY=4MB b.cpp
// emcc -o a.html a.cpp -s USE_PTHREADS=1 -sMAIN_MODULE -s INITIAL_MEMORY=4MB --preload-file b.so b.cpp #include <iostream>
#include <map>
#include <string>
#include <emscripten.h>
typedef void (*func_t)();
void hello() { std::cout << "hello\n"; }
void world() { std::cout << "world\n"; }
void __attribute__((constructor)) global_init()
{
void* addr = EM_ASM_PTR({
return Module["register_map"];
});
std::map<std::string, func_t> *register_map = reinterpret_cast<std::map<std::string, func_t> *>(addr);
std::cout << "start register_map:" << register_map << ", addr:" << addr;
(*register_map)["hello"] = hello;
(*register_map)["world"] = world;
}
|
Beta Was this translation helpful? Give feedback.
you can try this way, passing the address to Module for proxy, using more cpp style, dude
a.cpp