Windows下编译quickjs
第一步:安装msys
msys官网,
安装后配置镜像源镜像源地址及配置方式
之后打开msys2 ucrt64并安装如下工具
pacman -S mingw-w64-ucrt-x86_64-gcc
pacman -S mingw-w64-ucrt-x86_64-toolchain
pacman -S mingw-w64-ucrt-x86_64-dlfcn
pacman -S make
第二步:修改代码
打开quickjs-libc.c文件,找到js_module_loader函数
修改一行函数
if (has_suffix(module_name, ".so")|| has_suffix(module_name, ".dll")) {//添加部分为|| has_suffix(module_name, ".dll")
之后修改:#if defined(_WIN32)宏定义下的js_module_loader_so函数
static JSModuleDef *js_module_loader_so(JSContext *ctx,
const char *module_name)
{
JSModuleDef *m;
void *hd;
JSInitModuleFunc *init;
char *filename;
if (!strchr(module_name, '/')) {
/* must add a '/' so that the DLL is not searched in the
system library paths */
filename = js_malloc(ctx, strlen(module_name) + 2 + 1);
if (!filename)
return NULL;
strcpy(filename, "./");
strcpy(filename + 2, module_name);
} else {
filename = (char *)module_name;
}
/* C module */
hd = LoadLibrary(filename);//dlopen修改为LoadLibrary
if (filename != module_name)
js_free(ctx, filename);
if (!hd) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s' as shared library",
module_name);
goto fail;
}
init = (JSInitModuleFunc*)GetProcAddress(hd, "js_init_module");//dlsym修改为GetProcAddress
if (!init) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': js_init_module not found",
module_name);
goto fail;
}
m = init(ctx, module_name);
if (!m) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': initialization error",
module_name);
fail:
if (hd)
FreeLibrary(hd);//dlclose修改为FreeLibrary
return NULL;
}
return m;
}
之后,修改Makefile文件,取消
CONFIG_WIN32=y的注释,
并添加生成def文件的命令,三组代码根据makefile的内容排布自行插入
DEF_FILE = libquickjs.def
PROGS+=$(DEF_FILE)
$(DEF_FILE): $(QJS_LIB_OBJS)
@echo "EXPORTS" > $(DEF_FILE)
@nm $(QJS_LIB_OBJS) | grep ' T ' | awk '{print $$3}' >> $(DEF_FILE)
第三步:编译生成
生成静态库.a,可执行文件
make LDEXPORT="-static -s"
生成动态库dll
gcc -shared -o libquickjs.dll -static -s -Wl,--whole-archive libquickjs.a -lm -Wl,--no-whole-archive
之后,打开visualstudio的工具x64 native tools
定位到def文件生成路径下,输入 lib /DEF:libquickjs.def,得到lib文件
第四步:测试使用
将之前生成的lib与dll库复制到项目的目录与可执行文件的目录下,由于quickj代码有警告
所以可以在自己项目的顶部使用:#pragma warning(disable:4576),
或者在cmakelists中添加:add_compile_options(/wd4576)#禁用4576警告
//测试代码
//#pragma warning(disable:4576)
#include <iostream>
#include "quickjs-libc.h"
int main(int argc, char** argv)
{
//运行时
JSRuntime* rt = JS_NewRuntime();
//上下文
JSContext* ctx = JS_NewContext(rt);
std::string jsCode = R"(
function calculate(num1, num2, operator){
switch(operator){
case '+':
return num1 + num2;
case '-':
return num1 - num2;
}
}
)";
JSValue jsRes = JS_Eval(ctx, jsCode.c_str(), jsCode.length(), "<evalScript>", JS_EVAL_TYPE_GLOBAL);
if (JS_IsException(jsRes))
{
js_std_dump_error(ctx);
return 0;
}
JS_FreeValue(ctx, jsRes);
//参数设置
double dNum1 = 10, dNum2 = 20;
std::string strOperator = "+";
JSValue arg[3];
arg[0] = JS_NewFloat64(ctx, dNum1);
arg[1] = JS_NewFloat64(ctx, dNum2);
arg[2] = JS_NewString(ctx, strOperator.c_str());
//函数绑定
JSValue jsObject = JS_GetGlobalObject(ctx);
JSValue jsCalculate = JS_GetPropertyStr(ctx, jsObject, "calculate");
JS_FreeValue(ctx, jsObject);
JS_FreeValue(ctx, jsCalculate);
//调用函数
JSValue jsResult = JS_Call(ctx, jsCalculate, JS_UNDEFINED, 3, (JSValueConst*)arg);
if (JS_IsException(jsResult))
{
js_std_dump_error(ctx);
return 0;
}
//释放资源
JS_FreeValue(ctx, arg[2]);
JS_FreeValue(ctx, arg[1]);
JS_FreeValue(ctx, arg[0]);
double dValue;
if (JS_ToFloat64(ctx, &dValue, jsResult))
{
std::cout << " Call error " << std::endl;
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
JS_FreeValue(ctx, jsResult);
std::cout << "calculate " << dNum1 << " " << strOperator << " " << dNum2 << " = " << dValue << std::endl;
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
https://zhuanlan.zhihu.com/p/623863082
https://blog.csdn.net/slaltum/article/details/133142451
https://blog.csdn.net/yunfeiyang62/article/details/45949701
https://blog.csdn.net/w371584831/article/details/129025300