コンパイルlua 5.3拡張soファイルで発生したいくつかの問題のまとめ


最近linuxの下でluaの拡張関数を書いてみました.soファイル、出会ったいくつかの問題をまとめます
1.コンパイルする場合.cpp末尾のC++ファイルの場合、その関数関数の前に必ずextern"C"を付けます
コンパイルに遭遇した場合、次のような文字が表示されます.
/usr/bin/ld: /usr/local/lib/liblua.a(lapi.o): relocation R_X86_64_32 against `luaO_nilobject_' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/liblua.a: could not read symbols:     
collect2:   :ld    1
make: *** [mylib.so]    1

これはlualib.aはsoファイルのリダイレクトをサポートしていません.この問題は私に多くの時間をかけて、最後に海外の大神が答えました.
アドレス:http://superuser.com/questions/557884/getting-error-recompile-with-fpic
At this point in asterisk, you're trying to build a dynamic lib. Since this dynamic lib can be loaded at any memory location, everything needs to be relocatable. The -fPIC flag means Position Independent Code, the code is made to be independent of load location - loaded anywhere.

As part of this asterisk dynamic lib build, it's trying to bring in the Lua interpreter. Since it's bringing into a dynamic lib, it needs everything compiled PIC. But you're using a static lib of lua, which was not built with -fPIC. It rejects this, since the lua objects in the static lib can not be relocated. 

BTW: this is why adding -fPIC to the asterisk build won't help. It's not your asterisk code objects that are incompatible (which -fPIC can affect), but liblua.a, specifically the objects carried by liblua.a (e.g lapi.o). Besides, you're building a dynamic lib at that point, and Im sure you already have relocatable code flags such as -fPIC for the asterisk objects you're trying to pull together at that point.

I see three solutions. 

•One is to drop lua from your build. If you don't need it specifically and were thinking more that "this may be fun to play with later" you may be able to and not lose wanted features.


•Another is to get a dynamic version of liblua, liblua.so, one that can be referenced in your asterisk build. I don't know your distro, so I can't say how to get it.


•The other, more pain in the ass one, is to rebuild lua, and liblua.a, with -fPIC. You'd have compatibility issues maybe from inconsistent build flags (what you made and what else is on disk), so I think finding a liblua.so to match your currently built lua is the better option. 


If you find liblua.so, you may want to look into the '-rpath' linker flag for this though, specifically '-Wl,-rpath,/path/to/lua/libs'

このオオカミは3つの解決策を提供して、私は3つ目を使って、つまりluaを再コンパイルして、そしてluaをコンパイルする時コンパイルオプション-fPICを加えて、コンパイルが終わったら、やはりリンクすることができます(この真心の穴!)
luaを再コンパイルした後、私はまたどのようにCで拡張してluaに使用するかを見てみました.私がネット上のいろいろなテンプレートを押して書いたとき、luaがプログラムを実行して私の書いたものをロードしていることに気づきました.soファイルの場合、
Error: multiple Lua VMs detected
このエラーは、後でまたインターネットで探して、原因はcがluaを呼び出す時すでに1つのlua仮想機があったので、luaの中で拡張モジュールを呼び出すならば、必ずリンクしてlualibをリンクしないでくださいと言いました.aこれ、本当にめまいがします.
最後に彼らはコンパイル選択線-Wlを追加して-Eすればいいと説明した.
Don't link your C module with liblua.a when you create a .so from it. For examples, see my page of Lua libraries: http://www.tecgraf.puc-rio.br/~lhf/ftp/lua/ . You can link liblua.a statically into your main program but you have to export its symbols by adding -Wl,-E at link time. That's how the Lua interpreter is built in Linux.

注意[-WL,-E]はつながっているので、真ん中のカンマは取れませんよ
添付リファレンス:
luatest.cpp:
#include 
#include 
#include 
#include 
#include 

static int c_cont (lua_State *L, int status, lua_KContext ctx)
{
	printf("c_count status:%d
",status); printf("c_count ctx:%d
", ctx); return 0; } static int c_callback(lua_State *L){ /* lua_pcallk, lua_pcall */ lua_getglobal(L, "run"); int ret = lua_pcallk(L, 0, 0, 0, 0, c_cont); printf("ret = %d
",ret); if(ret) { fprintf(stderr, "Error: %s
", lua_tostring(L, -1)); lua_pop(L, 1); exit(1); } return 0; } int main() { struct lua_State * L; L = luaL_newstate(); luaL_openlibs(L); int ret = luaL_dofile(L,"main.lua"); if (ret != LUA_OK) { fprintf(stderr, "Error: %s
", lua_tostring(L, -1)); lua_pop(L, 1); return 0; } while (true) { printf("c:runing lua
"); // lua_getglobal(L, "run"); // lua_pcall(L, 0, 0, 0); c_callback(L); sleep(1); } return 0; }

mylib.cpp:
#include 
#include 
#include 
#include 
#include 

extern "C" int add(struct lua_State * L)
{
	double op1 = luaL_checknumber(L,1);
	double op2 = luaL_checknumber(L,2);
	lua_pushnumber(L,op1 + op2);
	return 1;
}

static struct luaL_Reg libs[] = {
		{"add", add},
		{NULL, NULL}
};

extern "C" int luaopen_mylib(struct lua_State * L)
{
	luaL_newlib(L, libs);
	return 1;
}

Makefile:
all : mylib.so test

mylib.so : lib.cpp
	g++ lib.cpp -fPIC -shared -llua -o mylib.so

test : luatest.cpp
	g++ -o test luatest.cpp -llua -ldl -lm -Wl,-E

main.lua:
--package.cpath = package.cpath .. ";*.a";
local co = nil;
local mylib = require("mylib");

local function cofunc()
	for i = 1,10 do
		print(i);
		if (i < 10) then
			coroutine.yield();
		end
	end
	local file = io.open("txt","a");
	print(file:read("*all"));
	co = nil
end

function run()
	print("lua runing..");
	if (nil == co) then
		co = coroutine.create(cofunc);
	end
	print(mylib.add(5200000,1314));
	coroutine.resume(co);
end