2010-08-26 3 views
9

У меня есть небольшое приложение, которое использует Lua, связанное как dll (не статическое). Я хочу загрузить свою собственную C++ - написанную dll через Lua, используя package.loadlib (libname, funcname). Для этого мне нужно экспортировать функцию, которая следует за протоколом Lua lua_CFunction. По этой причине я должен включить lua.h в свой проект и использовать функции Lua для передачи параметров и результатов. Итак, мои вопросы:Создание DLL на C++, загружаемое Lua

  1. Будет ли в моей DLL использовать Lua dll, которая уже загружена в процесс небольшого приложения?
  2. package.loadlib загружает и выгружает мою DLL немедленно, или моя DLL после загрузки остается до конца выполнения lua scrpit или завершения приложения?

ответ

8

Начиная с конкретными вопросами:

  1. Да, но только если ваша DLL неявно связана с ним. Будьте осторожны, потому что, если вы случайно связали две копии Lua VM в своем приложении, это может вызвать большую путаницу. В этом отношении аналогичные проблемы относятся и к среде исполнения C. Я бы загрузил все приложение под номером Dependency Walker, чтобы убедиться, что он относится только к одному экземпляру Lua DLL и одному времени выполнения C.

  2. Я понимаю, что package.loadlib() несет ответственность только за загрузку и привязку к названной функции в названной библиотеке. До тех пор, пока объект возвращенной функции (обозначающий lua_CFunction, который вы назвали), жив, тогда DLL загружается. Если вы потеряете последнюю ссылку на функцию, тогда библиотека может быть доступна для сбора мусора, и если она будет собрана, она будет выгружена. В списке рассылки Lua-L рассказывалось о том, как гарантировать, что определенная DLL будет выгружена, если это вас беспокоит. В противном случае, если вы просто предположите, что DLL загружена до тех пор, пока вы можете достичь функции, хранящейся в ней, вы будете в порядке.

Позвольте мне добавить, что модульная система, построенная поверх этого, является гораздо лучшим способом расширения Lua с помощью кода C или C++. Chapter 26 of Programming in Lua описывает это более подробно, и ссылка на эту главу в онлайн-копии первого издания (в котором описывается Lua 5.0). Обратите внимание, что модульная система немного изменилась в Lua 5.1 и снова в Lua 5.2. Может оказаться полезным получение копии второго или третьего изданий PiL (доступных как в бумажной, так и электронной форме через много книготорговцев).

Вот исполнительное резюме: Чтобы создать модуль с именем foo в C, вы создаете foo.dll, который экспортирует как минимум функцию с прототипом int luaopen_foo(lua_State *L). Эта функция должна загружать ваш модуль (обычно с помощью luaL_register() в Lua 5.1 или luaL_newlib() или luaL_setfuncs() в Lua 5.2 для регистрации таблицы, полной функций C) и возврата этой таблицы. На стороне Lua вы помещаете DLL куда-то по пути, описанному в package.cpath, а затем он может быть загружен кодом, например local foo = require "foo". Существуют и другие тонкие различия между различными версиями Lua 5.x, но относительно просто создать C-код, который может быть скомпилирован для любого из них.

Делая это, у вас есть преимущество в том, что модуль может быть загружен с пути, может быть написан либо в C, либо в Lua, либо в сочетании с обоими, и хорошо работает с другими модулями.Вы также можете загрузить столько или несколько C-функций, сколько вам нужно, с одним вызовом require.

+0

Большое спасибо за отличный ответ. Это мне очень помогло! Помимо функциональности Lua, я хочу, чтобы моя DLL подключалась к WndProc приложения и добавляла мою собственную панель инструментов, поэтому я не хочу, чтобы моя DLL была выгружена при обстоятельствах, о которых я не знаю. –

+1

Вы можете получить явный контроль над своим временем жизни, сохранив свою дополнительную ссылку на нее, которую вы только отпустите, когда будете готовы. Вы можете использовать 'luaL_ref()' с таблицей в 'LUA_REGISTRYINDEX', чтобы получить ссылку на любой объект, который может быть сохранен (в виде целого) на стороне C и выпущен с помощью' luaL_unref() '. – RBerteig

+0

Для тех, кто просто нахожу этот вопрос, начиная с Lua 5.2, 'luaL_register' устарел; Вместо этого следует использовать 'luaL_newlib', поскольку модули с динамической загрузкой не должны регистрировать что-либо в глобальной среде. – bcrist

-1

Вы можете динамически связываться с той же Lua-dll, что и в вашем приложении.

Что касается package.loadlib, я понятия не имею, как это работает. Прочтите источник?

Смежные вопросы