1. 程式人生 > >Lua使用動態連結庫呼叫C模組(VS2015)

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模組的過程。