Вопрос

Я использую 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))
Это было полезно?

Решение

Я вижу несколько вопросов. Я опишу их и предоставлю фрагмент кода, который должен работать так, как я полагаю, вы хотели, чтобы этот образец работал.

Ваша первая проблема заключается в том, что компилятор C ++ исказил имя единственной функции, экспортируемой из вашей DLL, имя которой имеет значение для Lua: luaopen_luapassing () . Стандартный бинарный дистрибутив для Windows был скомпилирован как программа на C и предполагает имя в стиле C для точки входа модуля DLL.

Кроме того, у вас немного неправильный протокол для функции luaopen_x . Функция возвращает целое число, которое сообщает Lua, сколько элементов на вершине стека Lua являются возвращаемыми значениями для использования Lua. Протокол, предполагаемый require , предпочел бы, чтобы вы оставили объект таблицы нового модуля на вершине стека и вернули его Lua. Для этого функция luaopen_x обычно использует luaL_register () , как вы это сделали, а затем возвращает 1.

Существует также проблема именования. Модули, написанные на чистом Lua, имеют возможность меньше знать свои имена. Но модули, написанные на C, должны экспортировать функцию из DLL, которая включает имя модуля в свое имя. Они также должны предоставить это имя модуля для luaL_register () , чтобы создать правильную таблицу и обновить ее в глобальной среде. Наконец, клиентский скрипт Lua увидит загруженный модуль в глобальной таблице с именем, подобным имени, переданному в require , который также возвращается из require , чтобы его можно было кэшировать в локальный в этом сценарии.

Пара других nits с кодом C состоит в том, что числовой тип действительно должен быть написан lua_Number для переносимости, и что было бы общепринятым использовать luaL_checknumber () вместо lua_tonumber () для принудительного применения обязательного аргумента функции. Лично я бы назвал реализацию C публичной функции с именем, связанным с ее именем, которое будет публично известно Lua, но это всего лишь вопрос вкуса.

Эта версия на стороне C должна исправить эти проблемы:

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

Затем образец сценария должен ссылаться на загруженный модуль по его собственному имени и на функции, определенные этим модулем по их собственным именам. Lua чувствителен к регистру, поэтому, если модуль создает функцию с именем dothis () , сценарий должен использовать это же имя и не может найти его с именем doThis () для пример.

require "luapassing"

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

Я должен добавить, что я на самом деле не скомпилировал и не запустил вышеописанное, так что в качестве упражнения могут быть опечатка или две;

Другие советы

Если вы собираетесь делать много привязки C ++ к lua, вы можете взглянуть на luabind .

Если вы компилируете как C ++ и хотите соответствовать интерфейсу 'C', вы должны объявить внешне видимые функции как extern " C " , чтобы избежать искажения имени.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top