Getting the normal Lua library to interact with GMod's Lua state?
17 replies, posted
For example, the normal Lua library creates a state like so
[code]lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);[/code]
How would I get it to interact with GMod's Lua state instead of creating a different one? I've tried
[code]int Test(lua_State* state)
{
lua_pushstring(state, "TEST");
lua_setglobal(state, "WHY_GOD");
return 0;
}[/code]but it crashes SRCDS. Is it even possible to do this?
[code]#include "raw/gmwrapper.h"
extern "C" {
#include "raw/lua.h"
#include "raw/lauxlib.h"
}[/code]With GMOD_MODULE_OPEN and GMOD_MODULE_CLOSE in the file, there are a few errors that say _gmod13_open and _gmod13_close are already defined. How do I use gmod13_open and gmod13_close?
Alright it's a bit tricky, I talked all day yesterday with the creator because I literally just got into module making and I found Garry's API to be terrible.
Anyway, there's a few things that you need.
First of all, install [url=http://code.google.com/p/luaforwindows/]Lua for Windows[/url].
When you've installed it, go to its installation folder and in there there's another folder called "include/", you want [I]that[/I] folder in your project (don't include any headers from Vanillin itself!).
When you've done that, you include the file "lua.h" and that is the only file you should actually include [I]in your code[/I].
Next, you want to link the [I]lua51.lib[/I] (a static library) to your project. If you don't know how to do that, a simple Google search should yield you results (it did for me).
To sum it all up, here's how things should look ([B]ignore the MySQL stuff![/B]):
[t]http://puu.sh/74uP7.png[/t]
[t]http://puu.sh/74uPW.png[/t]
[t]http://puu.sh/74uQC.png[/t]
But you're not done yet! As it seems, we have to manually export the entrypoint of our module. To do this, head to your Linker -> Command Line and write as follows: [I]/EXPORT:luaopen_<name of your project>[/I]
If you did that correctly, it should look something like this:
[t]http://puu.sh/74uSQ.png[/t]
Lastly, make [I]absolutely sure[/I] that you have his [url=http://www.facepunch.com/showthread.php?t=1226065]require fix[/url] and you should be good to go.
[editline]21st February 2014[/editline]
One extra thing! Make sure you include [I]<lua.hpp>[/I] and not [I]<lua.h>[/I] or else the function names get weird!
Here's an example project to clear it up:
[I]Module.h[/I]
[code]
#pragma once
#include <lua.hpp>
extern "C" {
int luaopen_test(lua_State* state);
}
[/code]
[I]Module.cpp[/I]
[code]
#include "Module.h"
int luaopen_test(lua_State* state)
{
lua_newtable(state);
return 1;
}
[/code]
Very in-depth explanation! I've got it all done except the command line part, which is confusing me a little as you said to use
[quote]/EXPORT:lua_open<name of your project>[/quote]
but in the picture it shows
[quote]/EXPORT:luaopen_test[/quote]
and the project name looks like it's gmsv_test on the top left of the screenshot. My project name is Test, and I've tried different combinations but all of them resulted in an unresolved external error.
Oh, that's a typo. If your project is called "stuff", your entry function should be called [I]"luaopen_stuff"[/I] and your command line option should be [I]"/EXPORT:luaopen_stuff"[/I].
I believe the function name is actually fairly arbitrary and that you can call it whatever you want as long as you export it correctly, but I am not entirely sure of that.
[editline]22nd February 2014[/editline]
Correction! The function name is [I]not[/I] arbitrary and must follow the format specified above.
[editline]22nd February 2014[/editline]
Oh and regarding your error, can you show it to me? Along with your code.
[QUOTE=EvacX;44001411]Oh, that's a typo. If your project is called "stuff", your entry function should be called [I]"luaopen_stuff"[/I] and your command line option should be [I]"/EXPORT:luaopen_stuff"[/I].
I believe the function name is actually fairly arbitrary and that you can call it whatever you want as long as you export it correctly, but I am not entirely sure of that.
[editline]22nd February 2014[/editline]
Correction! The function name is [I]not[/I] arbitrary and must follow the format specified above.
[editline]22nd February 2014[/editline]
Oh and regarding your error, can you show it to me? Along with your code.[/QUOTE]
It's fine now, I got it working. I made my project lowercase, added the extern "C" and int luaopen_test parts and it built with no errors. I installed the [B]require[/B] fix, loaded the server up, and got an error I don't think is supposed to be there.
[quote][ERROR] lua/autorun/server/test.lua:2: error loading module 'test' from file 'garrysmod\lua\bin\gmsv_test_win32.dll':
The specified procedure could not be found.
1. error - [C]:-1
2. searcher - lua/autorun/require_compat.lua:111
3. require - lua/autorun/require_compat.lua:168
4. unknown - lua/autorun/server/test.lua:2[/quote]
[cpp]int luaopen_test(lua_State* state)
{
lua_pushstring(state, "TEST");
lua_setglobal(state, "WHY_GOD");
return 0;
}[/cpp]
WHY_GOD should equal "TEST" but it doesn't when I try to print it out.
[B]All[/B] your code, please :v:
Sorry bout that. Here it is.
[B]main.cpp[/B]
[cpp]#include "Interface.h"
#include "Methods.h"
using namespace GarrysMod::Lua;
int luaopen_test(lua_State* state)
{
lua_pushstring(state, "TEST");
lua_setglobal(state, "WHY_GOD");
return 0;
}[/cpp]
[b]Methods.h[/b]
[cpp]#pragma once
#include <raw/lua.hpp>
extern "C" {
int luaopen_test(lua_State* state);
}[/cpp]
You're still including the old GMod interface, you shouldn't. Also, when I said [I]all[/I] your code, I meant the Lua code too. :v:
It crashes because you maybe pushes something to the stack but Gmod don't "take" this variable, so it stay in the stack and crash
PS : Dunno if my sentence make sence.
[QUOTE=EvacX;44005823]You're still including the old GMod interface, you shouldn't. Also, when I said [I]all[/I] your code, I meant the Lua code too. :v:[/QUOTE]
There's no way to use both? And I'm a bit confused because I don't actually have any Lua code. The only Lua code I have is the requiring of the module, and the code in my other reply is all the code that's in the project.
[lua]print("require module")
require("test")[/lua]
That's the only Lua code I have. Right now I'm just trying to get it to set a global variable when it opens but I'm getting that error from before. I have also removed [B]using namespace GarrysMod::Lua[/B]. Still no dice :(
[quote]The specified procedure could not be found.[/quote]
[QUOTE=ExtReMLapin;44005841]It crashes because you maybe pushes something to the stack but Gmod don't "take" this variable, so it stay in the stack and crash
PS : Dunno if my sentence make sence.[/QUOTE]
Nah, that's definitely not it.
Can you show me where you put the .dll and the .lua file from the require fix?
[editline]22nd February 2014[/editline]
Also what OS is your server using?
Author of Vanillin here; feel free to hit me up on Steam ("InfectiousFight") if you want some help, I should be available all day every weekday next week.
Vanillin is [b]not[/b] guaranteed to work if you try to use the Garry interface at the same time, and there's not really any need to; anything you can do in the Garry interface, you can do with the actual Lua C API.
Don't include any of the Garry headers; and if you're not actually using any features of C++, then just have your file compile explicitly in C mode anyway, you'll eliminate the chance for name-mangling problems to occur. I'm not exactly sure how to do that in Visual Studio, I only use the tools from the cmdline (but from there, it'd be passing your files using /Tc instead of /Tp). Note that "C mode" and "C++ mode" are file-specific and there's no problem mixing them a single project.
Lastly...try to run dumpbin.exe over your DLL, use the /EXPORTS option and show us the output. The program will be located at <path_to_visual_studio>\VC\bin\dumpbin.exe This is the fastest way to check if your DLL is [i]actually[/i] exporting your entrypoint function.
While you're at it, show us the exact command line VS is using to invoke the compiler and linker...I think you can get to it from Project > ProjectName Properties > Configuration Properties / ("C/C++" or "Linker") Properties > Command Line; then show us what you see there.
P.S. Another good reason to have LuaForWindows installed is so you can always build a regular-Lua version and a GLua-version of your binary modules at the same time. Being able to see what problems crop up when you try to use your module from regular Lua helps isolate the source of these exact kinds of problems.
[img]http://i.imgur.com/CBvoaWz.png[/img]
[img]http://i.imgur.com/dlKXFAy.png[/img]
I'm running this with SteamCMD on my computer, Windows 8.[QUOTE=Infectious;44006369]Author of Vanillin here; feel free to hit me up on Steam ("InfectiousFight") if you want some help, I should be available all day every weekday next week.[/QUOTE]
Will do! Thanks man.
I've removed the GMod interface and tried /Tc in the C/C++ command line. Some errors pop up with /Tc in it, but these errors disappear when I remove /Tc.
[IMG]http://i.imgur.com/ukAaQzA.png[/IMG]
[B]dumpbin /EXPORTS[/B]
[IMG]http://i.imgur.com/8bhbhhw.png[/IMG]
[B]C/C++[/B]
[quote]/GS /GL /analyze- /W3 /Gy /Zc:wchar_t /I"C:\Users\Duck\Documents\Visual Studio 2013\Projects\Test\Test\include" /Zi /Gm- /O2 /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "TEST_EXPORTS" /D "_WINDLL" /D "_MBCS" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\gmsv_test_win32.pch" [/quote]
[B]Linker[/B]
[quote]/OUT:"C:\SteamCMD\garrysmod\garrysmod\lua\bin\gmsv_test_win32.dll" /MANIFEST /LTCG /NXCOMPAT /PDB:"C:\SteamCMD\garrysmod\garrysmod\lua\bin\gmsv_test_win32.pdb" /DYNAMICBASE "lua51.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /IMPLIB:"C:\SteamCMD\garrysmod\garrysmod\lua\bin\gmsv_test_win32.lib" /DEBUG /DLL /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:\SteamCMD\garrysmod\garrysmod\lua\bin\gmsv_test_win32.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release\gmsv_test_win32.dll.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /LIBPATH:"C:\Users\Duck\Documents\Visual Studio 2013\Projects\Test\Test\lib" /TLBID:1 [/quote]
[B]main.cpp[/B]
[cpp]#include "Methods.h"
int luaopen_test(lua_State* state)
{
lua_pushstring(state, "TEST");
lua_setglobal(state, "WHY_GOD");
return 0;
}[/cpp]
[B]Methods.h[/B]
[cpp]#pragma once
#include <lua.hpp>
extern "C" {
int luaopen_test(lua_State* state);
}[/cpp]
[B]autorun/server/test.lua[/B]
[lua]print("require module")
require("test")[/lua]
Still getting the procedure error.
Wonderful! I think I've managed to track down your error.
I went and double-checked the sources for both Vanillin and my require() fix, and looked at the stuff you posted.
luaopen_test() is being exported just fine. It's gmod13_open() that [i]isn't[/i]...the code where the error is thrown from is looking for that, not your actual entrypoint.
Your DLL exports [i]should[/i] look like this:
[img]http://i.imgur.com/6foYuHd.png[/img]
Looking at your linker's invocation, I see that there is no /LIBPATH specifying the location for lua51.lib, lua51.lib is just being passed by name directly on the cmdline. That means link.exe is probably finding the location for it through a path specified in the LIB environment variable...which is probably being constructed by VS as part of a specific environment it invokes the linker in, so we can't look at that directly.
My guess is that you've somehow gotten the linker to use the lua51.lib [i]import library[/i] that comes with regular Lua, rather than the lua51.lib [i]static library[/i] that comes with Vanillin, since we're not otherwise seeing any linktime missing-symbol errors.
[b]So[/b], looking at the MSDN documentation, it looks like these things are controlled by [i]ProjectName Properties > Linker > General > Additional Library Directories[/i], and [i]ProjectName Properties > Linker > Input > Additional Dependencies[/i]. Double-check both of those, and make sure neither of them contains references to LuaForWindows' lib\ directory.
[QUOTE=Infectious;44011054]Wonderful! I think I've managed to track down your error.
I went and double-checked the sources for both Vanillin and my require() fix, and looked at the stuff you posted.
luaopen_test() is being exported just fine. It's gmod13_open() that [i]isn't[/i]...the code where the error is thrown from is looking for that, not your actual entrypoint.
Your DLL exports [i]should[/i] look like this:
[img]http://i.imgur.com/6foYuHd.png[/img]
Looking at your linker's invocation, I see that there is no /LIBPATH specifying the location for lua51.lib, lua51.lib is just being passed by name directly on the cmdline. That means link.exe is probably finding the location for it through a path specified in the LIB environment variable...which is probably being constructed by VS as part of a specific environment it invokes the linker in, so we can't look at that directly.
My guess is that you've somehow gotten the linker to use the lua51.lib [i]import library[/i] that comes with regular Lua, rather than the lua51.lib [i]static library[/i] that comes with Vanillin, since we're not otherwise seeing any linktime missing-symbol errors.
[b]So[/b], looking at the MSDN documentation, it looks like these things are controlled by [i]ProjectName Properties > Linker > General > Additional Library Directories[/i], and [i]ProjectName Properties > Linker > Input > Additional Dependencies[/i]. Double-check both of those, and make sure neither of them contains references to LuaForWindows' lib\ directory.[/QUOTE]
YES. THAT WAS IT, LOL.
I was indeed using the LuaForWindows lib instead of the Vanillin one. I switched it out and it worked flawlessly.
[img]http://i.imgur.com/D5zipSu.png[/img]
Thank you guys very much for your assistance. I'd never be able to get this done without you.
Sorry, you need to Log In to post a reply to this thread.