Pregunta

Estoy 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))
¿Fue útil?

Solución

Veo varios problemas. Los describiré y proporcionaré un fragmento de código que debería funcionar ya que creo que pretendía que esta muestra funcionara.

Su primer problema es que el compilador de C ++ modificó el nombre de la única función exportada desde su DLL cuyo nombre importa a Lua: luaopen_luapassing () . La distribución binaria de stock para Windows se compiló como un programa C y asume un nombre de estilo C para el punto de entrada del módulo DLL.

Además, tiene el protocolo para la función luaopen_x un poco incorrecto. La función devuelve un número entero que le dice a Lua cuántos elementos en la parte superior de la pila de Lua son valores devueltos para que los use Lua. El protocolo asumido por require preferiría dejar el objeto de la tabla del nuevo módulo en la parte superior de la pila y devolverlo a Lua. Para hacer esto, la función luaopen_x usaría normalmente luaL_register () como lo hizo, y luego devolverá 1.

También existe el problema de los nombres. Los módulos escritos en Lua puro tienen la oportunidad de ser menos conscientes de sus nombres. Pero los módulos escritos en C tienen que exportar una función desde la DLL que incluye el nombre del módulo en su nombre. También deben proporcionar ese nombre de módulo a luaL_register () para que la tabla correcta se cree y actualice en el entorno global. Finalmente, la secuencia de comandos de Lua del cliente verá el módulo cargado en una tabla global denominada como el nombre que se pasa a require , que también se devuelve de require para que pueda guardarse en caché un local en ese script.

Un par de otras nits con el código C es que el tipo numérico realmente debe estar escrito lua_Number para la portabilidad, y que sería convencional usar luaL_checknumber () en lugar de lua_tonumber () para imponer el argumento requerido a la función. Personalmente, nombraría la implementación en C de una función pública con un nombre relacionado con su nombre que será conocido públicamente por Lua, pero eso es solo una cuestión de gusto.

Esta versión del lado C debería solucionar estos problemas:

#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;
}

La secuencia de comandos de ejemplo debe referirse al módulo cargado por su nombre propio, y a las funciones definidas por ese módulo por su nombre propio. Lua distingue entre mayúsculas y minúsculas, por lo que si el módulo crea una función llamada dothis () , entonces el script debe usar el mismo nombre y no puede encontrarlo llamado doThis () , por ejemplo.

require "luapassing"

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

Debo agregar que en realidad no he compilado y ejecutado lo anterior, por lo que puede haber uno o dos errores tipográficos como ejercicio ;-)

Otros consejos

Si va a hacer una gran cantidad de enlaces de C ++ a lua, es posible que desee echar un vistazo a luabind .

Si está compilando como C ++ y desea hacer coincidir una interfaz 'C', debe declarar las funciones visibles externamente como extern " C " para evitar la manipulación de nombres.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top