Passing pointer to int in LUA FFI - ffi

I have a C function as follows
ffi.cdef[[
typedef struct {
int index;
char name[10];
} entry_key_t;
extern entry_t *lookup_entry(entry_key_t *key, int *err);
]]
I am having trouble passing the "int *" and I have tried the following variants,
local err_val = ffi.new("int[1]")
local err_val = ffi.new("int *")
The program crashes as the "err" passed to the function is NULL. (Pls note that I am able to pass pointer 'key' after doing ffi.new("entry_key_t[1]"))
What am I missing? I am using LuaJIT 2.0.2.

Not sure this will work for you but the pattern I've used for out params is:
local intPtr = ffi.typeof"int[1]"
local key = ffi.new("entry_key_t[1]")
local err = intPtr()
lookup_entry(key,err)
print(err[0])

Related

Trying to call function using a void pointer inside a variable type

In the firmware that I am writing, I created a type of variable. Similar to what is below:
struct SitemMenu {
unsigned int id;
char * text;
void * submenu
}
typedef struct SitemMenu TitemMenu;
Be any function:
void functionX () {
...
}
If I create this variable:
TitemMenu itemWhatever;
and do:
itemWhatever.submenu = &function (X);
Can I call functionX doing:
(*itemWhatever.submenu)();
I did something similar to this and the compiler give this answer:
error: (183) function or function pointer required
Yes you can, but not quite the way you've written it.
A function pointer is not declared in quite the same way as a 'normal' pointer.
What you need is:
struct SitemMenu {
unsigned int id;
char * text;
void (* submenu)(void); // this is a function pointer, as opposed to the 'normal' pointer above
};
typedef struct SitemMenu TitemMenu;
TitemMenu itemWhatever;
then, if you have some function declared with the same parameters and return type, like:
void functionX(), then you can do:
itemWhatever.submenu = functionX;
itemWhatever.submenu();

Pointer to constant string in struct

I'm writing in C.
In header1.h I declare a pointer to a constant string (a constant array of char), a new type with a struct and a variable of this type, and another variable:
const char *str_ptr = "Hello world!";
struct entry_t {
const char *text;
int var;
};
typedef entry_t entry;
extern entry start_entry;
int a;
In the file func.c I define the new variable:
#include "header1.h"
entry start_entry = {str_ptr, a};
void func(void)
{
//here i use start_entry
}
But the compiler report me the error
constant expression required
referring to the initialization of start_entry, and in particular of the const char* member.
Why? Where is the error?
Naturally if I define the string as
const char str[] = "Hello world!";
and then the entry variable as
entry start_entry = {&str, a};
everything is ok.
EDIT_1
I've made two errors in reporting my code:
var is const too
struct entry_t {
const char *text;
const int var;
};
in func.c entry is const too
const entry start_entry;
EDIT_2
I don't care of var, my interest is on const char * member (even if maybe the problem is the same: i write wrong code before, also with int var i had an error...).
I'm going to redefine all:
//header1.h
const char *str_ptr = "Hello world!";
struct entry_t {
const char *text;
};
typedef entry_t entry;
extern const entry start_entry;
//func.c
#include header1.h
const entry start_entry = {str_ptr};
void func(void)
{
//here i use start_entry
}
I can't understand why start_entry has a const char* member, i define it with a const char* but there is that error.
You can only use compile-time constants in initializers. The variable str_ptr is not even a run-time constant. What the const qualifier does is to prevent the string pointed to by str_ptr from being modified. The pointer itself can be reassigned. Therefor you need to initialize your start entry in an initialization function instead:
#include "header1.h"
entry start_entry;
void func(void)
{
//here i use start_entry
}
void init(void)
{
start_entry.text = str_ptr;
start_entry.var = a;
}
The problem is that with a C compiler you cannot initialize such statements in the global scope, it is considered as code outside a function:
(the same way that you cannot call a function to get tis return value and initialize a global outside a function)
entry start_entry = {str_ptr, a};
str_ptr is not really considered as a constant in C since it is seen as a pointer. The const qualifier does nothing here.
(the problem also occurs for me with a BTW, it looks that you are using some strange C++ compiler or a special C99 option see pmg comment)
When simply calling g++, your example works.
Note about your "naturally" statement:
entry start_entry = {&str, a};
compiles (with your compiler, gcc still rejects it because of a) but since you pass the address of the pointer, not the pointer itself => unspecified behaviour: not good.
If you want to do that, I suggest that you use a C++ compiler.
What works with simple gcc call:
char str_ptr[] = "Hello world!";
entry start_entry = {str_ptr, 12}; // considered as an array, value decided by the compiler, even if const keyword is missing
What doesn't
const char *str_ptr = "Hello world!";
entry start_entry = {str_ptr, 12}; // str_ptr is considered as a variable pointer even if const
entry start_entry = {"Hello world!", a}; // a is a variable: nocantdo
Where you are right is that char [] tells the compiler that the pointer is constant, even without the const keyword BTW, whereas the const keyword is not taken into account.
Notes:
I had to fix your code so it compiles with my gcc compiler:
typedef struct {
const char *text;
int var;
} entry;
extern entry start_entry;
Another point is: avoid declaring globals in header files as you'll get multiple inclusions or undefined symbols if you have more than one code file including it.

How to pass structure to callback function as an argument

I am learning C and trying to pass structure to call back function. Gone through online resources but unable to pass structure to call back function. Here is my code.
// myvariables.h
struct callbackStruct
{
int a;
int b;
int c;
};
extern struct callbackStruct callbackStructObject;
typedef void (*callback)(struct callbackStruct);
extern void callback_reg(callback pointerRefCallback);
// Operations.c
struct callbackStruct callbackStructObject;
void callback_reg(callback pointerRefCallback) {
(*pointerRefCallback)(callbackStructObject);
}
// main.c
struct callbackStruct myCallbackStruct1;
void my_callback(struct callbackStruct myCallbackStruct) {
printf("A value:%d" + myCallbackStruct.a);
}
int main()
{
callback ptr_my_callback = my_callback(myCallbackStruct1);
callback_reg(ptr_my_callback);
return 0;
}
Can anyone resolve this scenario?
The type callback is a function pointer type, e.g. a variable of that type is a pointer that points to a function that accepts a struct callbackStruct as single parameter:
typedef void (*callback)(struct callbackStruct);
So when you write (in main):
// ...
callback ptr_my_callback = // HERE
// ...
The expression at HERE must be the address of a function with the correct signature. You write:
my_callback(myCallbackStruct1);
Since my_callback is a function that returns nothing (void) and the above expression calls this function, the expression
callback ptr_my_callback = my_callback(yCallbackStruct1);
is not well formed (syntactically, as well as from the perspective of the type system).
Assuming that my_callback is the function that you want to work as a callback, you need to store its address in the pointer ptr_my_callback:
callback ptr_my_callback = &my_callback;
It's kind of unclear what your code is supposed to achieve, though, so I cannot really help you any further.

local static variable initialization by using global struct address values

My aim is to initialize a local static int variable.
I want to initialize my variable with the value that equals to offset value of a struct member.
My struct definition
struct member{
int ID;
char *NAME;
int NO;
};
Global Struct declaration
struct member FirstMember={.ID = 123, .NAME ="John", .NO=7382737};
struct member SecondMember={.ID = 120, .NAME ="Bill", .NO=454545};
Function and local static variable declaration
void foo()
{
static int offset = (int)(&FirstMember.NO - &SecondMember.ID );
}
Compiler output: Error[Pe028]: expression must have a constant value..
As far as I know static local variables must be initialized with const values. Compiler also knows the address values of the struct and its members. So compiler is able to calculate the difference between member addresses. But it returns an error message.
But this initialization works
void foo()
{
static int offset = (int)(&FirstMember.NO - &FirstMember.ID );
}
Could you please explain the point that I missed?
I think the problem is in your structure declaration: Name shoul be "char *" not "char" because you try to initialize it with "John" (type const char *).
This is working for me:
struct member{
int ID;
char* NAME;
int NO;
};
struct member FirstMember={123,"John",7382737};
void foo()
{
static int offset = (int)(&FirstMember.NO - &FirstMember.ID );
}
The second problem is that you want to initialize a "static" variable with an unknown value before run time.
All the static variables are in a separate place named "initialized data" section and the compiler needs to know exactly the value of each static variable at compile time because these values are "hardcoded" inside your binary file.
Even for this code:
int a = 10;
static int x = a;
you will have the same problem because "a" is not evaluated at compile time but at run-time.

C: array of void*

I'm using openCV and need some callback function. these callback function just accept limited parameters. So, if I need more variables for those function, I must make a global variables and turn it around between functions.
For example, here is the callback function :
void mouse_callback(int event, int x, int y, int flags, void* param);
// params : addition parameter, and just one, I need more parameters for this callback.
// but cannot, so make global variable.
And because I shouldn't do that (make global variable), so I decided to make array of (void*) but I afraid C cannot make this, because size of each members can be different.
My question is : can we make array of (void*), and if not, how can I overcome my problem : use callback function and don't need to make global variable.
Thanks :)
Define a struct that is capable of holding all necessary values and pass its address as the param argument:
struct my_type
{
int i;
char c;
};
void my_mouse_callback(int event, int x, int y, int flags, void* param)
{
struct my_type* t = param;
}
Not sure what the registration mechanism is but you need to ensure that the lifetime of the object pointed to by param is valid for the calling period of the callback function:
struct my_type* mouse_param = malloc(sizeof(*mouse_param));
mouse_param->i = 4;
mouse_param->c = 'a';
register_mouse_callback(my_mouse_callback, mouse_param);
Specifically, don't do this:
{
struct my_type mouse_param = { 4, 'a' };
register_mouse_callback(my_mouse_callback, &mouse_param);
} /* 'mouse_param' would be a dangling pointer in the callback. */
You can make array of void * because a pointer has a definite size, however, you cannot use these pointers without casting them.
You need to send a void* that points to a struct with your parameters. In the callback function you cast this type (void*) back to the struct* with your params like this:
typedef struct {
int event;
int x;
int y;
int flags;
} params;
void mouse_callback(void *data) {
params* param = (params*) data;
// now you can use param->x or param->y to access the parameters
}
To pass parameters you need create a paramstruct and cast its address to (void*):
paramstruct myparams;
myparams.x = 2;
myparams.y = 1;
mouse_callback( (void*) &myparams );

Resources