I want to experience with the Lua internals a little bit and affiliate myself with them. I figured digging into the C API would give me some neat knowledge. I wrote up a very small module (parser.dll) in pure C:
#include "parser.h"
#pragma comment(lib, "lua5.4.4.lib")
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int luaL_parse(lua_State* L) {
const char* path = lua_tostring(L, 1);
const char* cwd = lua_tostring(L, 2);
lua_getglobal(L, "print");
lua_pushstring(L, "Did this run?");
lua_callk(L, 1, 0, 0, NULL);
return 0;
}
static const struct luaL_Reg exports[] = {
{"parse", luaL_parse},
{NULL, NULL}
};
LUAMOD_API int luaopen_parser(lua_State* L) {
luaL_newlib(L, exports);
return 1;
}
Parser.h:
#pragma once
#ifndef lua_h
#include <lua.h>
#include <lauxlib.h>
#endif
int luaL_parse(lua_State* L);
And it compiles successfully. Whenever I try to require it (via require("parser")), I read this:
lua54.exe: error loading module 'parser' from file 'C:\Users\user\Desktop\Lua\parser.dll':
The specified module could not be found.
I feel like there's more of a mishap in my vs19 project configuration but I don't believe I can dump a text file of that configuration here. If you've any tips, please let me know! I'm not sure how to traverse the problem anymore, I've been attempting to hack at it for a little while.
One detail that may be important is that I'm building with the Lua 5.4.4 source code. As in, I downloaded the source, and just added it as an additional include directory.
On the Lua side, I don't get different results with package.loadlib either. That gives me nil even with funcname # "*".
Update, I went through a dependency walker (https://github.com/lucasg/Dependencies) and when I click on the Lua.5.4.4.dll dependency, it says it couldn't be found on the disk. Could the lib file perhaps be messed up? I'm not sure because the program compiles fine still, no unresolved symbols.
Related
I have a dll created using MSVC. The header file and a .def file are also present.
Here is what is exported from the dll (simple.def):
EXPORTS
simple_initialize
simple_step
simple_terminate
In1
Gain
Increment
I have a simple application that is trying to access the functions and variables inside the dll (have the .lib file as well). The MSVC project files have the necessary files provide and the application builds correctly. Here's the application code:
#include <stddef.h>
#include <stdio.h>
#include "simple.h"
#include "rtwtypes.h"
void main(void)
{
int i;
simple_initialize();
for (i = 0; i < 10; i++)
{
simple_step();
}
simple_terminate();
}
This code seems to be working fine, however, if I try to write to any of the global variables (In1, Gain or Increment) from the dll it results in a crash.
After researching I realized that the only way I can make it work is by adding
__declspec(dllimport) real_T In1;
AND
commenting out this line from the header file:
extern real_T In1;
If I do not comment this line, then I get following error:
Error C2370 'In1': redefinition; different storage class SimpleTest \SimpleTest.c 8
We have a repo that contains library functions for example (gcc is used to compile and link).
//print.h
#ifndef __PRINT_H_
#define __PRINT_H_
#define MAX_ARRAY 10
void print_hex(int cal[]);
#endif
// print.c
#include <stdio.h>
void print_hex(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf("%i\n",val[I]);
}
}
The above is compiled into a libprint.a.1.0.0. My app is then compiled using this library
//main.c
#include "print.h"
int main(int argc, int arg[]) {
int vals[MAX_ARRAY];
memset(vals,8,MAX_ARRAY*sizeof(int));
print_hex(vals);
return 0;
}
And everything is fine and works (assuming have typed the above out correctly). But then someone decides to make a change in the library where someone Makes the following change.
//print.h
...
#define MAX_ARRAY 50
...
The library is recompiled to libprint.a.1.1.0
This new static library is now used when compiling and linking our main.c. However, the new print.h was not copied to the include directory so the main.c is using an old print.h where MAX_ARRAY is smaller.
Now in this case we might get any behaviour as the print function runs off the end of the passed in array. As a user of the library there is no way to necessarily know that the header file is wrong until I compile and run the application, or perhaps even hours of running when the program starts to go crazy.
What is the standard way to avoid this issue?
Is there a way to add a version to a header file to ensure the correct library is linked?
I realise I could do this by creating a new function in print.c called get_version(), and use that in main.c to check against some defines in print.h to ensure veracity but I was wondering if there was a way without the user application having to specifically check library and header versions at run time.
Yes. And don't do it.
The libfuse library uses a macro FUSE_USE_VERSION that should be defined by the client to differentiate between different versions. Internally it works similar to feature_test_macros.
So in your library it would look like:
print.h:
#ifndef __PRINT_H_
#define __PRINT_H_
#if PRINT_USE_VERSION == 1
#define MAX_ARRAY 10
void print_hex_version_1(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_1(val);
}
#elif PRINT_USE_VERSION == 2
#define MAX_ARRAY 50
void print_hex_version_2(int cal[]);
static inline
void print_hex(int cal[]) {
print_hex_version_2(val);
}
#else
#error unknown PRINT_USE_VERSION
#endif
#endif
print_version_1.c:
#define PRINT_USE_VERSION 1
#include <stdio.h>
void print_hex_version_1(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
print_version_2.c:
#define PRINT_USE_VERSION 2
#include <stdio.h>
void print_hex_version_2(int val[]) {
for (int I=0;I<MAX_ARRAY;I++) {
printf(“%i\n”,val[I]);
}
}
Or similar, hope you'll you get the idea. Using this method you can distribute all possible versions of your library at once. And clients can link against multiple versions of your library. Which ends up being spaghetti code, unstable, unreliable, unfixable and unmaintainable.
On a global scale, it makes no sense. Just create a api that isn't dependent on a macro definition and take the array size as an argument. Check if the size of the array is equal to some predefined value and notify your client with error code that he did something wrong.
I am studying C with a textbook, and it has of course a lot of example source code for me to practice.
I had no problem with managing these code files when I was just studying with gcc, a text editor and terminal.
And now I wanted to use an IDE so I can get hints before compiling each source code, so downloaded one and trying to put every code file into a single project template the IDE offers.
The code files are usually short, and always have main function for each, so creating a project and importing all of them prevented me from compiling: I have multiple main function which I should have not.
Here is an example so I can describe what the problem I have:
I now started 7th chapter in the book, so I created a project named 'ch7'. And I have currently two example codes. The project can't be compiled with all the codes at once, so I commented every main function in each of the examples and made a new main.c, containing the main function part from the examples.
example code 1 (find.c) - has 6 functions, including 1 main function (I made it so it's now in comment block)
#include <stdio.h>
#include <string.h>
int NUM_ADS = 7;
char *ADS[] = { ... };
int sports_no_bieber(char* s) { ... }
int sports_or_workout(char* s) { ... }
int ns_theater(char* s) { ... }
int arts_theater_or_dining(char* s) { ... }
void find(int (match)(char*) ) { ... }
/* int main() { ... } */
example code 2 (test_drive.c) - has 7 functions and 1 structure, including 1 main function.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int compare_scores(const void* score_a, const void* score_b) { ... }
int compare_scores_desc(const void* score_a, const void* score_b) { ... }
typedef struct { ... } rectangle;
int compare_areas(const void* rect_a, const void* rect_b) { ... }
int compare_names(const void* name_a, const void* name_b) { ... }
int compare_areas_desc(const void* rect_a, const void* rect_b) { ... }
int compare_names_desc(const void* name_a, const void* name_b) { ... }
/* int main() { ... } */
I commented the main function for each codes because I wanted to use them in a new main.c:
#include <stdio.h>
#include <stdlib.h>
#include "find.c"
#include "test_drive.c"
// this list will grow as I make more example codes and include them like this.
// And yes, I know this part brings problem. I shouldn't directly include code files like this.
int main(int argc, char** argv) {
/*
statements for main function in example code 1;
*/
statements for main function in example code 2;
// this part is uncommented, because I am testing this one.
/*
statements for other example codes will be here after...
*/
return(EXIT_SUCCESS);
}
This of course returned compile errors: multiple definition of the functions.
I know I can make a header and put function declarations for every function existing in all the example codes, and then include that header to my new main.c.
But is this the only way to manage all example codes in a single project in an IDE? The files I've shown here is only two, but a header for them should have 11 function declarations. And I have lot more example codes, from chapter 1 to 6, including about 30 c files (and much more total amount of functions in each c file of course), some h, csv and txt files for specific example source codes.
If I have to make a header for all of them, it wouldn't be only consuming lots of time but also will force me to add another few lines to the header every time I write a new code as I keep studying.
It seems much ineffective compared with just writing a code file in a text editor, opening terminal and calling gcc to compile it.
So I think there should be much effective way to manage such example code files in a single place, which shouldn't only be a 'project'. I want to find a way in which I can get advantages of using IDE while code file management doesn't go too complicated.
Remove Main from all the files.
Create another files for Main.
Segregate all the files and implement everything in a procedure/function as you wanted.
In your Main file include only those file which you need and do the operation as you wanted.
As you go further in chapter try to keep the logic in particular procedure/ function such that you can again reuse it in the Main file.
Since it is really high level, i am assuming you are going through the chapters and trying the examples.
I created a DLL in eclipse like so:
created a C-Project -> shared library (MinGW) -> Name: testdll
created a header- and a source-file with an simple TestFunction
The source-file is like:
#include <stdio.h>
#include "test.h"
void write(){
printf("hallo von der dll\n");
}
Then I build it and under Debug a libtestdll.dll was created.
That looked good for me so far.
Now I created a C-Hello World-Project called usedll.
The file looks like this:
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
int main(void) {
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
write();
printf("done\n");
return EXIT_SUCCESS;
}
I created a lib-Folder under project usedll. I copied the libtestdll.dll and the test.h into this folder.
With a right-click on project usedll -> Properties -> C++Build -> Settings -> GCC C Compiler -> Includes -> add (added the lib-Folder from same project usedll)
Then under MinGW C Linker -> Libraries -> Libraries - I added the string libdll
and under Library Search Path I added the lib-folder from the usedll-Project.
The project was now build without errors, but when I executed it, the write-function does not produced any output.
Does someone see what I do wrong ?
Please read this ...
http://www.mingw.org/wiki/sampledll
I'll add a snippet below, but I feel you might not have exported your function, reading the above will explain how to do this (using MinGW).
( This snippet has been taken directly from the above webpage )
#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif
void __stdcall EXAMPLE_DLL hello(const char *s);
Please take note of the use of __declspec(dllexport) and __declspec(dllimport)
I'm trying to call a function from a C project but I don´t know how to do it.
Here is my code ("treatments.c"):
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
static int treatments_load_image (lua_State * L) {
lua_pushnumber(L,10);
return 1;
}
static const luaL_Reg RegisterFunctions[] =
{
{ "treatments", treatments_load_image },
{ NULL, NULL }
};
int luaopen_treatments(lua_State *L)
{
lua_newtable(L);
#if LUA_VERSION_NUM < 502
luaL_register(L, NULL, LuaExportFunctions);
#else
luaL_setfuncs(L, LuaExportFunctions, 0);
#endif
return 1;
}
In my .lua file, I´m trying to do something like this:
local treatments = require 'treatments'
And I get the error below:
lua: run.lua:15: module 'treatments' not found:
no field package.preload['treatments']
no file './treatments.lua'
...
The ".c" file is in the same folder than ".lua" file. I'm not using any MAKEFILE file.
If it helps, I'm using Lua 5.1 =)
Thanks!!
The ".c" file is in the same folder than ".lua" file. I'm not using
any MAKEFILE file
No, you must build your c source file into shared library (dll for windows, or so for linux), then put that shared library in lua package.cpath, see http://lua-users.org/wiki/ModulesTutorial
Lua's require deals with files containing Lua code or shared libraries in the case of C. You need to compile the C source code into a shared library and then load that, which should "return" a table (i.e. push it onto the stack), as usual.