Emscripten EMSCRIPTEN_KEEPALIVE / EXPORTED_FUNCTIONS from hpp/cpp files other then main - clang++

I have a c++ webassembly module with several function that is called wasmExec.wasm. So far i have been exporting methods from c++ to JavaScript that are located in the cpp file where the main() method is located using the EMSCRIPTEN_KEEPALIVE keyword. That is working just fine. I do see those methods when i do
wasm-nm wasmExec.wasm
and i can call them from JavaScript and get the expected result. In order achieve clean methods name i have been disabling C++ name mangling.
Now i have tried to use EMSCRIPTEN_KEEPALIVE with static methods that are not located in the main.cpp file instead in a separate namespace and separate cpp and header files. In those classes i am also using EMSCRIPTEN_KEEPALIVE but unfortunately the produced wasm module is eliminating my method and thus i can not see them when executing wasm-nm wasmExec.wasm althout they are marked with EMSCRIPTEN_KEEPALIVE in the header as well as in the cpp file. i.e. here is an example
#ifndef API_REGISTRATION_REGISTRATIONMANAGER_H_
#define API_REGISTRATION_REGISTRATIONMANAGER_H_
#include <string>
#include <emscripten/emscripten.h>
using namespace std;
namespace api::registration {
#ifdef __cplusplus
extern "C" {
#endif
class RegistrationManager {
public:
explicit RegistrationManager();
virtual ~RegistrationManager();
static char* EMSCRIPTEN_KEEPALIVE registerClient(
char* userNameInputPtr, int userNameLength
);
};
#ifdef __cplusplus
}
#endif
}
#endif /* API_REGISTRATION_REGISTRATIONMANAGER_H_ */
I am using cmake to compile the project. In the target properties i have explicitly defined EXPORTED_FUNCTIONS to be equal to
set_target_properties(wasmExec PROPERTIES LINK_FLAGS "-std=c++17 -s WASM=1 -s TOTAL_MEMORY=512MB -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=1 -s VERBOSE=1 --pre-js /Projects/src/wasm/preModule.js -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s EXPORTED_FUNCTIONS='['registerClient']' -s EXTRA_EXPORTED_RUNTIME_METHODS='['cwrap', 'getValue', 'setValue', 'registerClient' ]' " )
What could be the reason to not be able to register this the method "registerClient" within the webassembly module. I have even tired to use the option -s EXPORT_ALL=1 but that did not exported all the know methods as i was expcting it to do
I am compiling everything statically here i.e. below is the example of the registration_api cmake sub-folder
MESSAGE( STATUS "ADDING API_REGISTRATION_DIR")
set( API_REGISTRATION_SRC
RegistrationManager.h RegistrationManager.cpp
)
set(LIB_TYPE STATIC)
add_library(api_registration ${LIB_TYPE} ${API_REGISTRATION_SRC} )
target_include_directories(api_registration PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/")
the compilation process is successful with emscripten, nevertheless i do get this warrning exactly about the method i am trying to export:
em++: warning: undefined exported function: "registerClient" [-Wundefined]
if i put that method in the main.cpp it is automatically exported without any problem.
My question is what could be the reason why this export is not working when the method is located in external cp/hpp file?
Addition 15 May 2020: I was able to register the method only if i remove the class definition, change the namesapce to the one that main have. Then it seems that the underscore in the EXPORTED_FUNCTIONS is important i.e. -s EXPORTED_FUNCTIONS='['_registerClient']' . That worked for me. I was under the impression that if i use static methods that should work with classes as well, but it seems that not to be the case.
#ifndef API_REGISTRATION_REGISTRATIONMANAGER_H_
#define API_REGISTRATION_REGISTRATIONMANAGER_H_
#include <string>
#include <emscripten/emscripten.h>
using namespace std;
namespace wasm {
#ifdef __cplusplus
extern "C" {
#endif
char* EMSCRIPTEN_KEEPALIVE registerClient(
char* userNameInputPtr, int userNameLength
);
#ifdef __cplusplus
}
#endif
}
#endif /* API_REGISTRATION_REGISTRATIONMANAGER_H_ */
thus my question has changed to: Can emscripten register a static method of a class with EMSCRIPTEN_KEEPALIVE or not?

Related

Unknown symbol in module / v7_flush_dcache_all undefined in linux kernel module

I'm trying to create a linux kernel module that will disable the data cache. I'm trying to use the v7_exit_coherency_flush(all) function in arch/arm/include/asm/cacheflush.h, and this function calls v7_flush_dcache_all, which I found is in arch/arm/mm/arch-v7.S.
My issue is that when I try to make my module, I get a warning
WARNING: "v7_flush_dcache_all [/home/pi/Documents/ARMHammer/kern/my_kernel/cache_disable.ko] undefined!
and when I try to insert the module I get an error
insmod: ERROR: could not insert module cache_disable.ko: Unknown symbol in module
So it looks like that ach-v7.S file isn't being read. I tried simply including it in my main file, but that produced a lot of errors, probably because its an assembly file.
I'm pretty much stuck at this point, is there someway I can include the assembly file in the Makefile, or maybe I'm not including all of the necessary .h files?
For what its worth, here's my main file
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h> /* For current */
#include <linux/tty.h> /* For the tty declarations */
#include <linux/version.h> /* For LINUX_VERSION_CODE */
#include <linux/mm.h>
#include <asm/cp15.h>
#include <asm/cacheflush.h>
#include <asm/glue-cache.h>
#include <asm/shmparam.h>
#include <asm/cachetype.h>
#include <asm/outercache.h>
// #include "my_cache-v7.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Jay Salzman");
static void print_string(char *str)
{
struct tty_struct *my_tty;
#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,5) )
my_tty = current->tty;
#else
my_tty = current->signal->tty;
#endif
if (my_tty != NULL) {
((my_tty->ops)->write) (my_tty, /* The tty itself */
#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9) )
0, /* Don't take the string
from user space */
#endif
str, /* String */
strlen(str)); /* Length */
#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9) )
((my_tty->ops)->write) (my_tty, 0, "\015\012", 2);
#else
((my_tty->ops)->write) (my_tty, "\015\012", 2);
#endif
}
}
static int __init print_string_init(void)
{
v7_exit_coherency_flush(all);
print_string("The module has been inserted. Hello world!");
return 0;
}
static void __exit print_string_exit(void)
{
print_string("The module has been removed. Farewell world!");
}
module_init(print_string_init);
module_exit(print_string_exit);
and my Makefile
obj-m += cache_disable.o
KDIR = /home/pi/linux/
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
Also, if anybody knows an easier way to disable the cache, I'm all ears!
v7_exit_coherency_flush() is for power management code to take a CPU out of the kernel cleanly in order to power it off - it's not callable from random modules for very good reason. If you really want to lose data and crash the machine in weird and subtle ways, you might as well just bypass kernel functions entirely and use a trivial inline asm to hit the SCTLR directly*.
I dread to imagine what you're trying to achieve, but if you really want to run Linux (painfully slowly) with the cache off, you'll need to rebuild the kernel, turning off CONFIG_SMP in order to turn on CONFIG_CPU_DCACHE_DISABLE. That's the only vaguely supported method which might work.
* I'm not even going to explain that, it's that terrible an idea.

dlclose() static destructors run at different times if function is virtual

I'm using dlopen() and dlclose() to load and unload a module. The module contains some static data which needs to be destructed when dlclose() is called. However I'm finding that under certain circumstances dlclose() does not call the destructors - instead they are only called when main() exits.
I've boiled my code down to this. I have a class which contains a virtual function getType() defined inside the class, making reference to static data. I also have a StaticDestructionChecker object which just prints when the static constructors and destructors are being called. Finally I have a main() function that loads everything else via dlopen(), closes it via dlclose() and prints when main() is finished:
module1.h
#ifndef MODULE1_H
#define MODULE1_H
class MyClass
{
public:
MyClass();
virtual ~MyClass();
virtual int& getType() const
{
static int t(123);
return t;
}
};
#endif // MODULE1_H
module1.cpp
#include <stdio.h>
#include "module1.h"
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
class StaticDestructionChecker
{
public:
StaticDestructionChecker()
{
printf("Constructing static data\n");
}
~StaticDestructionChecker()
{
printf("Destructing static data\n");
}
};
StaticDestructionChecker checker;
main:
#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
void* handle = dlopen("module1.so", RTLD_NOW);
if (!handle) printf("dlopen error: %s\n", dlerror());
dlclose(handle);
printf("end of main\n");
return 0;
}
Running all this as-is causes the static data to be destructed after main terminates, ie the output is:
Constructing static data
end of main
Destructing static data
The problem is with the virtual/static combo in getType(). If I change getType() to be non-virtual OR if I remove the "static int t", the destructors get called when expected, ie output is:
Constructing static data
Destructing static data
end of main
Is there a way to get the correct destruction order while still keeping the virtual/static code? FYI this is a simplified version of a sort of custom RTTI system, where getType() is automatically generated via a DECLARE_xxx macro, so I don't want to move the implementation into the cpp file because there would need to be a second macro call in there too.
I am using GCC 4.8 on Ubuntu 12.
Thanks
See dlclose() doesn't work with factory function & complex static in function?
If you use gold linker than passing --no-gnu-unique flag when linking module1.so fixes the problem:
]$ g++ -o module1.so -shared -fPIC -Wl,--no-gnu-unique module1.cpp
]$ g++ main.cpp -ldl
]$ LD_LIBRARY_PATH=. ./a.out
Constructing static data
Destructing static data
end of main
I don't know what are other consequences of using that flag.

How to compile <linnux/kernel.h> in Linux gcc compiler?

I have a simple question. I want to compile the following c file:
#include <linux/kernel.h>
#include <linux/module.h>
#include <sys/syscall.h>
extern void *sys_call_table[];
asmlinkage int (*original_sys_open)(int);
asmlinkage int our_fake_open_function(int error_code)
{
/*print message on console every time we
* *are called*/
printk("HEY! sys_open called with error_code=%d\n",error_code);
/*call the original sys_exit*/
return original_sys_open(error_code);
}
/*this function is called when the module is
* *loaded (initialization)*/
int init_module()
{
/*store reference to the original sys_exit*/
original_sys_open=sys_call_table[__NR_open];
/*manipulate sys_call_table to call our
* *fake exit function instead
* *of sys_exit*/
sys_call_table[__NR_open]=our_fake_open_function;
}
/*this function is called when the module is
* *unloaded*/
void cleanup_module()
{
/*make __NR_exit point to the original
* *sys_exit when our module
* *is unloaded*/
sys_call_table[__NR_open]=original_sys_open;
}
The problem is that gcc -I/usr/src/kernels/2.6.32-279.el6.x86_64/include myfile.c generates a unsolvabe include dependency which can be found in .
Please tell me how to fix this gcc compiler problem I am encountering today. Thank you very much for your insight.
How to build external modules is documented in the documentation:
$ make -C <path_to_kernel_src> M=$PWD

where do i include the string library in my C++ header file

My simple class won't compile in Visual Studio. It worked before I added the string company member and the getter method getCo() to it. I think I need to put #include the string standard library somewhere but I am not sure where. Any idea where? In my header file, I have:
#pragma once
#ifndef ENGINEER_H_
#define ENGINEER_H_
class engineer {
int years;
string company;
public:
engineer(int years);
~engineer(void);
int getYears();
string getCo();
};
#endif ENGINEER_H_
And in my CPP file for the definition of the class, I have:
#include "StdAfx.h"
#include "engineer.h"
engineer::engineer(int y, string c){
years = y;
company = c;
}
engineer::~engineer(void) {
}
int engineer::getYears() {
return years;
}
string engineer::getCo() {
return company;
}
Put it in the header file, and prefix your usage of string with the namespace std.
Header:
#include <string>
class engineer
{
std::string company;
};
In the implementation file (.cpp) you can prefix the names or have a using directive.
Implementation:
using namespace std; // using directive, no longer need to use std::
Avoid putting the using directive in a header file, as that pollutes the global namespace and can cause problems with naming collisions in other libraries you may wish to use.
Put it in the header file, after the include guards:
#include <string>
using std::string;
This way, it will also be available for your cpp file, and you don't have to include it again.
BTW, the #pragma once and #ifndef ENGINEER_H_ serve the same purpose. You can have only one of them. Code generated by VC use the #pragma, which is shorter and doesn't add a definition, so that's what I'd use (no harm if you leave both, though).

threading from a static member in dll

I have a problem lunching a thread within a class A for example where the class A is a static member of class B with in a dll. I am using Visual Studio 9 and boost 1.40. Please consider the following code:
mylib.h:
#include <boost/thread.hpp>
#include <windows.h>
#ifdef FOO_STATIC
#define FOO_API
#else
#ifdef FOO_EXPORT
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
#endif
class FOO_API foo{
boost::thread* thrd;
public:
foo();
~foo();
void do_work();
};
class FOO_API bar{
static foo f;
public:
static foo& instance();
};
mylib.cpp:
#include "mylib.h"
foo::foo()
{
thrd = new boost::thread(boost::bind(&foo::do_work,this));
}
foo::~foo(){
thrd->join();
delete thrd;
}
void foo::do_work(){
printf("doing some works\n");
}
foo& bar::instance(){return f;}
foo bar::f;
in the executable application, I have:
main.cpp:
#include "mylib.h"
void main(){
bar::instance();
}
If I link mylib statically to the executable app, It prints out "doing some works", while if I link it dynamically (dll), it does nothing.
I really appreciate any help.
Your program could be exiting before the thread completes. You might try waiting after the bar::instance() call, or joining the thread in main. Something else to try would be to flush stdout after the printf call.
From the MSDN documentation:
If your DLL is linked with the C
run-time library (CRT), the entry
point provided by the CRT calls the
constructors and destructors for
global and static C++ objects.
Therefore, these restrictions (*) for
DllMain also apply to constructors and
destructors and any code that is
called from them.
(*) The restrictions include communicating with threads.
It's best to make the global variable a pointer, and construct and release the object in dedicated callback routines.
See also this helpful SO answer.

Resources