Lua crases when loading dll extension - c

I'm trying to create a Lua dll extension on Windows. I'm using Lua 5.3. My compiler is from MinGW and is gcc 4.9.3.
My C code for the dll extension is something like this:
#include <stdio.h>
#include <lua.h>
static int dub(lua_State *L) {
const double a = lua_tonumber(L, 1);
lua_pushnumber(L, a*2);
return 1;
}
__declspec(dllexport) int __cdecl luaopen_mylib(lua_State *L){
printf("One\n");
lua_pushcfunction(L, dub);
printf("Two\n");
lua_setglobal(L, "dub");
printf("Three\n");
return 1;
}
I'm compiling my dll like this:
gcc mylib.c -shared -o mylib.dll -llua
The idea being that I can load it from Lua and use it like this:
require "mylib"
print (dub(5)) --should print 10
However, when I actually try to run the Lua code, it crashes on the require "mylib" line. The DLL is able to print "One" and "Two", but it does not get to print "Three" before it crashes. This tells me the problem may be with the 'lua_setglobal' call.
What's going wrong? How to I debug it further or fix it?
As a bonus question: what should the return value of luaopen_mylib be?
Thanks!

I compiled your code and it works fine. So your problem isn't from your code. My guess is that you're using different versions of Lua, or the linking is somehow going wrong.
There are three places a version mismatch could occur.
In your #include <lua.h> line
In your build line with -llua
When you run the lua executable
It is vital that all three of these be the same lua version. If one is mismatched, that could cause the problem you're having. I would guess that your lua executable version doesn't match the others.
One other thing to try, is that your dll should link against the lua dll. There should be a file on your system called lua53.dll. Copy it to your build directory. When you compile with gcc, try this instead:
gcc mylib.c -shared -o mylib.dll lua53.dll
This means that your dll extension calls the exact same lua code that the lua executable is using. They way you have it now, with the -llua line, it appears that you are linking in lua statically. This is almost never what you want for a dll library, because the lua executable will be calling code in lua53.dll while your dll is calling separate code in the static library. I don't think this alone is causing your crash, but it's not good practice. If lua used global state (it doesn't), this linking issue could certainly cause your crash. Also, if you compile against lua53.dll you'll find that mylib.dll is much smaller.
In summary, I think you have a lua version mismatch somewhere that is causing your crash. You should also link against the lua dll instead of the static library for good form.
As a bonus question: what should the return value of luaopen_mylib be?
In your code it should actually be 0 instead of 1 as you have. The return value is the number of things left on the stack that you want the require() call to return. Your library is just shoving itself into the global state and not returning any lua values. An alternative way to do things is to return a table with the library's functions in it. That way you don't pollute global state. Since your library has only one function, you could return it directly like this:
__declspec(dllexport) int __cdecl luaopen_mylib(lua_State *L){
lua_pushcfunction(L, dub);
return 1;
}
Then you use it from lua as:
local dub = require("mylib")
print (dub(5)) --should print 10
I prefer this way since the caller can decided what to name the imports and it doesn't pollute global space.

Related

Using GDB without debug symbols

Assume the following code:
#include <iostream>
void test(){
//
}
int main(){
return 0;
}
Compiling whiteout -g I'm still able to set a breakpoint on main and test using GDB.
How is that possible? Is it related to symbol tables?
(gdb) b test
Breakpoint 1 at 0x400512
Here's what you're missing.
C++ is built around the concept of compiling and then linking. As such, during the compilation stage, the compiler assumes that the current file is just one file in a more complex program that will be eventually linked together.
When you write:
void test(){
//
}
The compiler has no choice but to assume that test is going to be called by code from another source file, and that will be compiled into a separate .o file. As such, it exports test's symbol despite the fact that no debug symbols are defined.
To see this effect in action, try the following. First, mark test as static. If you compile with optimization, you will see that test is no longer visible to gdb. In fact, it is no longer even defined. The compiler inlines it away.
Another way of making this happen is by passing g++ the -fwhole-program option. This option tells gcc to assume the current file being compile is the whole program, no other compilation unit will exist. This allows it, effectively, to treat all function and global definitions as static. Again, once you turn on optimizations, you will see that test is no longer visible to gdb.

Given .dll, .lib, and .h, and would like to write a C program using a function in the DLL

So, I have TVZLib.h, TVZlib.dll, and TVZlib.lib, and I am using gcc to compile the following program (it's a simple test case). The complier gives me the error:
"undefined reference to '_imp__TVZGetNavigationMatrix'"
Yet. when I comple the program with a different type of parameter for the function's call, it complains that it's not the correct parameter (requires *float). To me, that means that it at least has found the function, as it knows what it wants.
From my research, I can tell that people think it's to do with the linking of the library, or the order in which I link, but I've tried all of the gcc commands in all combinations, and all give me the same error, so I'm desperate for some help.
#include <stdlib.h>
#include <stdio.h>
#include "TVZLib.h"
int main() {
float floatie = 2;
float *ptr = &floatie;
TVZGetNavigationMatrix(ptr);
getchar();
return 0;
}
Thanks a lot in advance!
My compiler command:
gcc dlltest.c -L. TVZLib.lib
The header file (TVZLib.h).
And the direct output:
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccuDpoiE.o:dlltest.c:(.text+0x2c): undefined reference to `_imp__TVZGetNavigationMatrix'
collect2: ld returned 1 exit status
It's been a while since I've been compiling natively on Windows...
Did you intend to link statically against TVZlib.lib? That's not happening.
By default, gcc will pick the dynamic version of a library if it finds both a static and a dynamic lib. If you want to force gcc to link statically, you can use the -static option.
If memory serves me right the _imp__ prefix is a sign that a DLL was loaded (_imp__ symbol prefix is used for the trampoline function that calls into the DLL).

Compile C program using dlopen and dlsym with -fPIC

I am having a problem about a wrong symbol resolution. My main program loads a shared library with dlopen and a symbol from it with dlsym. Both the program and the library are written in C.
Library code
int a(int b)
{
return b+1;
}
int c(int d)
{
return a(d)+1;
}
In order to make it work on a 64-bit machine, -fPIC is passed to gcc when compiling.
The program is:
#include <dlfcn.h>
#include <stdio.h>
int (*a)(int b);
int (*c)(int d);
int main()
{
void* lib=dlopen("./libtest.so",RTLD_LAZY);
a=dlsym(lib,"a");
c=dlsym(lib,"c");
int d = c(6);
int b = a(5);
printf("b is %d d is %d\n",b,d);
return 0;
}
Everything runs fine if the program is NOT compiled with -fPIC, but it crashes with a segmentation fault when the program is compiled with -fPIC. Investigation led to discover that the crash is due to the wrong resolution of symbol a. The crash occurs when a is called, no matter whether from the library or the main program (the latter is obtained by commenting out the line calling c() in the main program).
No problems occur when calling c() itself, probably because c() is not called internally by the library itself, while a() is both a function used internally by the library and an API function of the library.
A simple workaround is not use -fPIC when compiling the program. But this is not always possible, for example when the code of the main program has to be in a shared library itself. Another workaround is to rename the pointer to function a to something else. But I cannot find any real solution.
Replacing RTLD_LAZY with RTLD_NOW does not help.
I suspect that there is a clash between two global symbols. One solution is to declare a in the main program as static. Alternatively, the linux manpage mentions RTLD_DEEPBIND flag, a linux-only extension, which you can pass to dlopen and which will cause library to prefer its own symbols over global symbols.
It seems this issue can take place in one more case (like for me). I have a program and a couple of a dynamically linked libs. And when I tried to add one more I used a function from a static lib (my too) in it. And I forgot to add to linkage list this static lib. Linker was not warn me about this, but program was crushing with segmentation fault error.
Maybe this will help for someone.
FWIW, I ran into a similar problem when compiling as C++ and forgetting about name mangling. A solution there is to use extern "C".

Prevent name mangling in C (not C++) with MinGW for dynamic symbol search

I have a C program where I get function pointers "dynamically" by the function name (ie. I pass the function name as a string and get a pointer to the function). I already do this in Linux using dlopen and dlsym and I suppose it will also work in any other Unix-like with dlfcn.
The problems began when I tried to port this program to Windows using MinGW. When I try to find the name using "GetProcAddress(handle, symbol_name), where "symbol_name" is the name of my callback function and "handle" is a handle to the current executable returned by "GetModuleHandle(NULL)", I get nothing because the MinGW name mangling adds an "_" to my symbol name.
The obvious solution (prefix an "_" to the symbol I want) seems a bit 'dangerous' for portability (may the compiler add two underscores for some of them? I don't know), so, I ask:
There is a better way to prevent the compiler from name-mangling my symbols? (or a subset of them, only the callbacks I need to find dynamically);
Or a way to make GetProcAddress find them even when mangled?
I also tried the option -fno-leading-underscore, but it removed the mangling of all the external symbols too, making the program impossible to link with the stdlib, etc. (also, the warnings on the documentation are a bit scary).
Also, please note that I'm using pure C -- there is no C++ in any part of my code -- and all my code lives in a single ".exe".
TIA
Not sure what your problem is, as I can't reproduce it with the simplest DLL example I can think of:
/* hello_dll.c */
#include <stdio.h>
__declspec(dllexport) void hello ( void )
{
puts ( "Hello, DLL!");
}
/* hello_exe.c */
#include <windows.h>
#include <stdio.h>
int main () {
typedef void (*pfunc)(void);
HANDLE hself;
pfunc hello;
hself = GetModuleHandle(NULL);
hello = (pfunc)GetProcAddress(hdll, "hello");
hello();
return 0;
}
This is the command line using MinGW gcc with no special flags, and it all works:
gcc src\hello_dll.c src\hello_exe.c -o bin\hello.exe
$ bin\hello.exe
Hello, DLL!
$ gcc --version
gcc (GCC) 4.5.0
It doesn't work without the __declspec(dllexport) if you are getting the function from yourself; when creating a DLL with gcc -shared it doesn't appear to be necessary, but appears to be required if exporting a function from an exe.
C doesn't use name mangling. In particular, it doesn't add any type information to the name (unlike C++). But some platforms make a small modification to the name like prefixing the underscore. And unlike C++, it's only platform specific but not compiler specific.
On all the platforms I've seen so far, I've only seen either no modification or the leading underscore.
So I propose you use some ifdefs to derive whether the current platform uses an underscore or not.
(Windows has another small modification for certain Windows API functions for distinguishing the ANSI from the Unicode version. But that's probably not relevant for your case.)
Maybe somebody else can point at some official documentation for the C ABI on different platforms.

in C, how to use function from main program file in a shared library file

c and i use it to generate x.so shared library
in x.c i want to use few functions that are in the main module, (dir containing main files and exe), kind of recursive dependeny.
is there a way to do this (without copying those functions in x.c) ?
i read about -rdynamic , but could not get it fully.
when i compile i get 'somefunc' undeclared. (somefunc is in main module, i did extern somefunx in x.c but did not work)
please let me know
thanks
You could define the affected methods in your shared library to take the call back function pointer arguments, and then at call time pass the main module's functions as arguments. E.g.
// Library
void dosomething (int arg, void (*callback)(void)) { ... }
// Main module
void called_from_lib(void) { ... }
dosomething(10, called_from_lib);
This looks like unix. There is a function, dlopen(), that lets you dynamically call a function in a library - without referencing it at compile time and without linking it into the program. dlopen() is POSIX, and so should be on any modern unix box.
Example here:
http://www.dwheeler.com/program-library/Program-Library-HOWTO/x172.html
There is also LD_LIBRARY_PATH. This environment variable lets you use the same code, but allows you to substitute in a library that was not there at compile time. This is not exactly what you are asking, but it can be made to do something along the lines of using adhoc shared libraries without resorting to dlopen. Some systems like HPUX also support SHLIB_PATH which does the same thing.

Resources