Lua"コントロール"C

17424 ワード

前言
あなたは今この文章を見て、少なくともあなたもLua言語を勉強していることを説明しました.仕事が必要だから?Luaが面白いから?どんな理由があっても、とにかくLuaはNBのスクリプト言語です.実は、Lua言語自体は機能が非常に限られており、比較的単調な言語であり、標準ライブラリも非常に平凡であり、そのNBのところは、C、C++などの高級言語と完璧に「私通」できることにある.私たちはC、C++言語を使ってLuaに完璧なライブラリを書いて、Luaに呼び出すことができます.ここで、LuaにCを「コントロール」させる方法をよくまとめます.
基本的な知識
上で述べたように、C、C++を使ってライブラリを書いてLuaに呼び出させます.これが拡張Luaです.アプリケーションは新しいC関数をLuaに登録します.そうすれば、LuaはCを「制御」することができます.言うのは簡単そうですが、実はそうではありません.
LuaはC関数を呼び出すことができるが、Luaが任意のC関数を呼び出すことができるという意味ではない.「C「制御」Lua」では、C言語がLua関数を呼び出すと、Luaにパラメータを渡し、Luaから結果を取得するための簡単なプロトコルに従う必要があります.同様に、Luaによって呼び出されるC関数についても、パラメータを取得し、結果を返すプロトコルに従う必要があります.また、ある適切な方法で関数アドレスをLuaに伝えるために、C関数を登録する必要があります.
LuaがC関数を呼び出すときも、C言語がLuaを呼び出すときと同じスタックが使用されます.C言語はスタックから関数パラメータを取得し、結果をスタックに押し込む.スタック内で関数結果を他の値と区別するために、C関数はスタックに押し込まれた結果の数を返す必要があります.
スタックはグローバルな構造ではなく、重要な概念です.各関数には独自のローカルプライベートスタックがあります.LuaがC関数を呼び出すと、最初のパラメータは常にこのローカルスタックのインデックス1である.このC関数がLuaコードを呼び出し、Luaコードに同じC関数が呼び出されても、これらのC関数呼び出しは自分のプライベートスタックしか見えず、最初のパラメータはインデックス1です.
C関数を登録する必要があると述べたが、ここではLuaに登録されているすべての関数が同じプロトタイプを有し、このプロトタイプはlua.hで定義され、プロトタイプは以下の通りである.
typedef int (*lua_CFunction) (lua_State *L);

このC関数にはLuaの状態というパラメータが1つしかないことがわかる.スタックに押し込まれた戻り値の数を示す整数を返します.戻ると、Luaはスタックの結果の下にあるコンテンツを自動的に削除します.したがって、この関数は、結果を圧入する前にスタックを空にする必要はありません.
練習しないのは空手だ
前に言ったように、Luaの底はCです.だから私たちはLuaの解釈器のソースコード(lua.c)に私たちのC関数を加えて、それからこのLua解釈器を再コンパイルして、exe解釈器を得てから、私たちの関数を呼び出すことができます.私がこんなにたくさん言ったと信じています.あなたはきっと霧の水に違いありません.いいでしょう.あなたはそうすべきです.
  • ここにLuaのソースコードをダウンロードします.はい、Luaはオープンソースです.
  • ソースコードのファイルの説明に従って、ソースコードをコンパイルして、あなたがどんなツールを使っても(私はVisual Studio 2013を使っています)、それをコンパイルします.もしあなたがコンパイルについてまだ分からないと言ったら、私に教えてください.私はあなたを助けます.
  • そうです.DLLと解釈器を手に入れるだけでいいです.コンパイラを手に入れる必要はありません.

  • さあ、私たちのC関数コードを加えましょう.Luaが私たちのC関数を呼び出すことができます.
  • はluaにある.cファイルには、
    // This is my function
    static int testFunc(lua_State *L)
    {
    	//           
    	lua_pushnumber(L, 10);
    	printf("Hello World");
    	return 1;
    }
  • という関数定義が追加されています.
  • pmain関数でluaL_Openlibs関数の後に以下のコードを追加します:
    lua_pushcfunction(L, testFunc);
    lua_setglobal(L, "Test");
  • これはLuaにC関数を登録することに相当する.次に解釈器を再コンパイルし、exeファイルを得て、このexeファイルを実行しましょう.以下のように実行します.
    何を待っているのか,君も急いでやってみなさい.コンパイルしたファイルをダウンロードするには、ここをクリックします.
    Cモジュール
    私たちはluaにいますcファイルにコードを追加すると、誰かが言ったように、人のコードを修正するのはどういうことですか.どのようにモジュールの開発を行って、私は自分で1つのモジュールを定義して、Luaに直接私のモジュールを呼び出すようにすればいいです.はい、大丈夫です.今、どのようにCモジュールを開発して、Luaに私たちが開発したCモジュールを呼び出すかについて話します.
    「Luaのモジュールとパッケージ」でも述べたように、Luaモジュールはプログラムブロックであり、通常tableのエントリとして格納されるいくつかのLua関数が定義されている.Luaのために記述されたCモジュールはこの挙動を模倣することができる.C関数の定義に加えて、CモジュールはLuaモジュールのメインブロックに相当する特殊な関数を定義する必要があります.モジュール内のすべてのC関数を登録し、適切な場所に格納し、モジュール内のすべての初期化が必要なものを初期化する必要があります.
    Luaはこの登録プロセスを通じてC関数を記録し,これらの関数アドレスを用いて直接呼び出す.すなわち,LuaがC関数を呼び出す場合,関数名,パケットの位置,可視性ルールに依存せず,登録時に入力された関数アドレスのみに依存する.通常、CモジュールにはCモジュールを作成するための共通(外部)関数が1つしかありませんが、他のすべての関数はプライベートであり、C言語でstaticとして宣言されています.
    OOPとモジュールの開発について今日、コードをCモジュールに設計することが望ましい.以下の利点があります.
  • は今後の拡張に便利である.
  • コードの集中管理を容易にする.
  • コード配布が容易です.

  • 次に、Lua呼び出しのためのCモジュールを作成します.このようなCモジュールを定義するには、主に次のタスクを実行します.
  • はモジュール関数を定義し、このモジュールが提供できるいくつかの機能関数である.
  • luaL_を定義するRegタイプの配列で、配列の各要素はluaL_です.Reg構造で、この構造には2つのフィールド、1つの文字列、1つの関数ポインタがあります.
  • は最後に主関数を宣言し、すべての関数を登録します.

  • コードを貼り付けます.
    #ifndef _TESTLIB_H
    #define _TESTLIB_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
    
    #ifdef TESTLIB_EXPORTS
    #define TESTLIB_EXPORTS __declspec(dllexport) 
    #else
    #define TESTLIB_EXPORTS __declspec(dllimport)
    #endif
    
    //      ,    ,            
    TESTLIB_EXPORTS int luaopen_testLib(lua_State *L);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    これはヘッダファイルです.このヘッダファイルに慣れていない学生は、「Visual StudioでC++を使用してDLLを作成し、使用する」という文章に移行してください.
    #include 
    #include "testLib.h"
    
    static int testFunc(lua_State *L)
    {
    	printf("http://www.jellthink.com
    "
    ); lua_pushnumber(L, 10); return 1; } static const struct luaL_Reg myLib[] = { {"test", testFunc}, {NULL, NULL} }; int luaopen_testLib(lua_State *L) { luaL_register(L, "testLib", myLib); return 1; // , 1 }

    これが主な実装ファイルで、主にluaL_を使用します.register関数は登録機能を完了します.以下はLuaテストコードです.
    require "testLib"
    local a = testLib.test()
    print(a)

    requireは自主的にtestLibを検索します.dllファイル、もちろんLinuxシステムではtestLibであるべきです.soファイルです.ここをクリックしてプロジェクトファイルをダウンロードします.