Domanda

Sto usando Visual Studio 2005.

------------------------ [luapassing.cpp] ------------------ -

#include "lua.h"
static int myCfunc (Lua_State *L){
   double trouble = lua_tonumber(L,1);
   lua_pushnumber(L,16.0 -trouble);
   return 1;
}
int luaopen_luapassing (Lua_State *L){
   static const lua_reg Map [] = {{"dothis",myCfunc},{NULL,NULL}};
   luaL_register(L,"cstuff",Map);
   return;
}

------------------------- [csample.lua] ----------------- --------

package.cpath = "./CLua2.dll"
require "luapassing"

print("hola")
print(seth.doThis(120))
È stato utile?

Soluzione

Vedo diversi problemi. Li descriverò e fornirò un frammento di codice che dovrebbe funzionare come credo tu abbia voluto che questo esempio funzionasse.

Il tuo primo problema è che il compilatore C ++ ha modificato il nome dell'unica funzione esportata dalla tua DLL il cui nome è importante per Lua: luaopen_luapassing () . La distribuzione binaria di stock per Windows è stata compilata come programma C e assume un nome di stile C per il punto di ingresso del modulo DLL.

Inoltre, il protocollo per la funzione luaopen_x è leggermente sbagliato. La funzione restituisce un numero intero che indica a Lua quanti elementi in cima allo stack di Lua sono valori di ritorno che possono essere utilizzati da Lua. Il protocollo assunto da richiedono preferirebbe lasciare l'oggetto tabella del nuovo modulo in cima allo stack e restituirlo a Lua. Per fare ciò, la funzione luaopen_x userebbe normalmente luaL_register () come hai fatto, quindi restituire 1.

C'è anche il problema della denominazione. I moduli scritti in pura Lua hanno l'opportunità di essere meno consapevoli dei loro nomi. Ma i moduli scritti in C devono esportare una funzione dalla DLL che include il nome del modulo nel suo nome. Devono anche fornire quel nome del modulo a luaL_register () in modo che la tabella giusta sia creata e aggiornata nell'ambiente globale. Infine, lo script Lua del client vedrà il modulo caricato in una tabella globale denominata come il nome passato a richiedono , che viene anche restituito da richiedono in modo che possa essere memorizzato nella cache un locale in quello script.

Un paio di altre lendini con il codice C sono che il tipo numerico dovrebbe davvero essere scritto lua_Number per la portabilità e che sarebbe convenzionale usare luaL_checknumber () anziché lua_tonumber () per applicare l'argomento richiesto alla funzione. Personalmente, nominerei l'implementazione C di una funzione pubblica con un nome correlato al suo nome che sarà conosciuto pubblicamente da Lua, ma è solo una questione di gusti.

Questa versione del lato C dovrebbe risolvere questi problemi:

#include "lua.h"
static int my_dothis (Lua_State *L){
   lua_Number trouble = luaL_checknumber(L,1);
   lua_pushnumber(L,16.0 -trouble);
   return 1;
}
extern "C" int luaopen_luapassing (Lua_State *L){
    static const lua_reg Map [] = {
        {"dothis", my_dothis},
        {NULL,NULL}
    };
    luaL_register(L,"luapassing",Map);
    return 1;
}

Lo script di esempio deve quindi fare riferimento al modulo caricato con il suo nome proprio e alle funzioni definite da quel modulo con i loro nomi propri. Lua fa distinzione tra maiuscole e minuscole, quindi se il modulo crea una funzione denominata dothis () , lo script deve utilizzare lo stesso nome e non può trovarlo denominato doThis () , per esempio.

require "luapassing"

print("hola")
print(luapassing.dothis(120))

Dovrei aggiungere che in realtà non ho compilato ed eseguito quanto sopra, quindi potrebbero esserci un errore di battitura o due come esercizio ;-)

Altri suggerimenti

Se stai facendo molto C ++ con lua binding, potresti dare un'occhiata a luabind .

Se si sta compilando come C ++ e si desidera abbinare un'interfaccia 'C', è necessario dichiarare le funzioni visibili esternamente come extern & C; per evitare la modifica del nome.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top