Lua使用动态链接库调用C模块(VS2015)

创建一个win32项目,起名mylib(因为我已经创建过mylib了,所以这里用的mylib2)。

这里写图片描述
下面开始编写C模块:

mylib.h如下:

/*mylib.h*/

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <dirent.h>
#include <errno.h>

extern "C" {
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
}

using namespace std;

#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif

extern "C"  __declspec(dllexport) MYLIB_API int luaopen_mylib(lua_State* L);

mylib.cpp如下(这里包含了两个函数功能,一个是l_sin函数,一个是遍历目录的l_dir函数):

// mylib.cpp : 定义 DLL 应用程序的导出函数。

#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "mylib.h"
#include <iostream>
#include <string>
#include <dirent.h>
#include <errno.h>

extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}

extern "C" int l_sin(lua_State *L) {
    double d = luaL_checknumber(L, 1);
    lua_pushnumber(L, sin(d));
    return 1;
}

extern "C" int l_dir(lua_State *L) {
    DIR *dir;
    struct dirent *entry;
    int i;
    const char *path = luaL_checkstring(L, 1);
    dir = opendir(path);
    if (dir == NULL) {
        lua_pushnil(L);
        lua_pushstring(L, strerror(errno));
        return 2;
    }

    lua_newtable(L);
    i = 1;
    while ((entry = readdir(dir)) != NULL) {
        lua_pushnumber(L, i++);
        lua_pushstring(L, entry->d_name);
        lua_settable(L, -3);
    }

    closedir(dir);
    return 1;
}

static const struct luaL_reg mylib[] = {
    { "mydir", l_dir },
    { "mysin", l_sin },
    { NULL, NULL }
};


extern "C"  __declspec(dllexport)
MYLIB_API int luaopen_mylib(lua_State* L) {
    luaL_register(L, "mylib", mylib);
    return 1;
}

这里尤其注意

extern "C"  __declspec(dllexport)
MYLIB_API int luaopen_mylib(lua_State* L)

extern “C” 和 dllexport,dll需要导出符号。

同时extern “C”避免名字粉碎。
extern “C”的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。

比如说你用C 开发了一个DLL 库,为了能够让C ++语言也能够调用你的DLL输出(Export)的函数,你需要用extern “C”来强制编译器不要修改你的函数名

编写好程序后,直接点击编辑生成mylib.dll和mylib.lib文件,会出现如下提示,忽略它就好。

这里写图片描述

然后将生成的mylib.dll和mylib.lib文件放到与lua程序的同目录下,这里创建一个lua文件叫做lib.lua:

mylib = require ("mylib");
print (mylib.mysin (3.14 / 2));
t = mylib.mydir ("D:\\Lua-5.1\\lua-5.1.5\\lua-5.1.5");
for k, v in pairs (t) do
    print (k, v);
end

如此lib.lua会通过require将动态库mylib链接到lua,并寻找luaopen_mylib函数,将其注册为一个lua函数,然后调用它以打开模块。运行结果如下:

这里写图片描述

如此就完成了整个lua采用动态链接库调用C模块的过程。

发布了141 篇原创文章 · 获赞 28 · 访问量 16万+
展开阅读全文

lua5.3 require自己导出的dll失败,报错PANIC: unprotected error in call to Lua API

05-06

dll工程代码(工程中lua使用的是动态链接方式) ``` #include <windows.h> #include "lua.hpp" int lua_sum(lua_State* L) { return 123; } static const luaL_Reg lua_xk_lib[] = { { "sum", lua_sum }, { NULL, NULL } }; extern "C" __declspec(dllexport) int luaopen_foo(lua_State* L) { printf("%s", "111111111111111\n"); luaL_newlib(L, lua_xk_lib); return 1; } ``` lua测试工程代码(工程中lua使用的是静态链接方式) ``` #include <stdio.h> #include <tchar.h> #include "lua.hpp" int _tmain(int argc, _TCHAR* argv[]) { lua_State *L = luaL_newstate(); luaL_openlibs(L); if (luaL_dofile(L, "main.lua")) { luaL_error(L, "!!!!!!"); } int i = 0; i++; return 0; } ``` main.lua ``` print("!!!!!!!!!!!!!!!!!!!============1") require "foo" print("!!!!!!!!!!!!!!!!!!!============") ``` vs2013写了个dll工程导出(工程中lua使用的是动态链接方式),想在lua里面加载这个dll,一直加载不成功。lua代码直接是require "foo", 调试的时候能去到printf("%s", "111111111111111\n");这行,然后下一行就报错了。错误输出是:PANIC: unprotected error in call to Lua API ![图片说明](https://img-ask.csdn.net/upload/201905/06/1557156013_529138.png) 查资料说是dll是用lua动态链接库的话,测试工程也需要是动态库,我修改后发现还是不行,一样报错,实在不清楚原因了,希望有大佬能指点一二。 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览