Using C variable inside Lua alongside nested functions - c

This is a sort of followup to my previous question about nested registered C functions found here:
Trying to call a function in Lua with nested tables
The previous question gave me the answer to adding a nested function like this:
dog.beagle.fetch()
I also would like to have variables at that level like:
dog.beagle.name
dog.beagle.microchipID
I want this string and number to be allocated in C and accessible by Lua. So, in C code, the variables might be defined as:
int microchipIDNumber;
char dogname[500];
The C variables need to be updated by assignments in Lua and its value needs to be retrieved by Lua when it is on the right of the equal sign. I have tried the __index and __newindex metamethod concept but everything I try seems to break down when I have 2 dots in the Lua path to the variable. I know I am probably making it more complicated with the 2 dots, but it makes the organization much easier to read in the Lua code. I also need to get an event for the assignment because I need to spin up some hardware when the microchipIDNumber value changes. I assume I can do this through the __newindex while I am setting the value.
Any ideas on how you would code the metatables and methods to accomplish the nesting? Could it be because my previous function declarations are confusing Lua?

The colon operator (:) in Lua is used only for functions. Consider the following example:
meta = {}
meta["__index"] = function(n,m) print(n) print(m) return m end
object = {}
setmetatable(object,meta)
print(object.foo)
The index function will simply print the two arguments it is passed and return the second one (which we will also print, because just doing object.foo is a syntax error). The output is going to be table: 0x153e6d0 foo foo with new lines. So __index gets the object in which we're looking up the variable and it's name. Now, if we replace object.foo with object:foo we get this:
input:5: function arguments expected near ')'
This is the because : in object:foo is syntactic sugar for object.foo(object), so Lua expects that you will provide arguments for a function call. If we did provide arguments (object:foo("bar")) we get this:
table: 0x222b3b0
foo
input:5: attempt to call method 'foo' (a string value)
So our __index function still gets called, but it is not passed the argument - Lua simply attemps to call the return value. So don't use : for members.
With that out of the way, let's look at how you can sync variables between Lua and C. This is actually quite involved and there are different ways to do it. One solution would be to use a combination of __index and __newindex. If you have a beagle structure in C, I'd recommend making these C functions and pushing them into the metatable of a Lua table as C-closures with a pointer to your C struct as an upvalue. Look at this for some info on lua_pushcclosure and this on closures in Lua in general.
If you don't have a single structure you can reference, it gets a lot more complicated, since you'll have to somehow store pairs variableName-variableLocation on the C side and know what type each is. You could maintain such a list in the actual Lua table, so dog.beagle would be a map of variable name to one or two something's. There a couple of options for this 'something'. First - one light user data (ie - a C pointer), but then you'll have the issue of figuring out what that is pointing to, so that you know what Lua type to push in for __index and what to pop out for __newindex . The other option is to push two functions/closures. You can make a C function for each type you'll have to handle (number, string, table, etc) and push the appropriate one for each variable, or make a uber-closure that takes a parameter what type it's being given and then just vary the up-values you push it with. In this case the __index and __newindex functions will simply lookup the appropriate function for a given variable name and call it, so it would be probably easiest to implement it in Lua.
In the case of two functions your dog.beagle might look something like this (not actual Lua syntax):
dog.beagle = {
__metatable = {
__index = function(table,key)
local getFunc = rawget(table,key).get
return getFunc(table,key)
end
__newindex = function(table,key,value)
local setFunc = rawget(table,key).set
setFunc(table,key,value)
end
}
"color" = {
"set" = *C function for setting color or closure with an upvalue to tell it's given a color*,
"get" = *C function for getting color or closure with an upvalue to tell it to return a color*
}
}
Notes about the above: 1.Don't set an object's __metatable field directly - it's used to hide the real metatable. Use setmetatable(object,metatable). 2. Notice the usage of rawget. We need it because otherwise trying to get a field of the object from within __index would be an infinite recursion. 3. You'll have to do a bit more error checking in the event rawget(table,key) returns nil, or if what it returns does not have get/set members.

Related

How to pass GoLang's struct's method as C callback

In Go source I have
type T struct {
// some data
}
func (t *T)M(arg0 SomeType1) {
// some computations
}
var Obj *T
In C sources I have
// SomeType1C is equivalent to SomeType1.
typedef void (*CallbackFunc)(SomeType1C);
// callback will be called !after! register_callback function returns.
void register_callback(CallbackFunc callback);
I would like to use Obj.M as callback for register_callback in C.
On MS Windows for winapi I pass smth like C.CallbackFunc(unsafe.Pointer(syscall.NewCallback(Obj.M))) to register_callback for this (not sure is it fully correct, but at least this works). But where is no NewCallback for non-Windows systems.
PS:
I'm sure that callback is registered after T is initialised and removed before T is removed.
I may have multiple instances of T and some of them may be used to callback's 'source' at same time (so T is not some kind of singltone).
Function pointer callbacks in GoLang's wiki uses gateway function, but I don't see how to adequate use it with struct's method.
Base idea:
Use exported callback as a proxy between C and Go:
//export callback
func callback(data0 SomeType1C, data1 Data){ // data1 - data passed to register_callback_with_data
obj := convertDataToObj(data1)
obj.M(data0)
}
and register it like this:
register_callback_with_data(callback, convertObjToData(obj));
Where are 3 ways: wrong (and easy), limited (medium) and right (hard).
Wrong (and easy) way:
Pass pointer to Go struct into C (as in original answer). This is totally wrong because Go runtime can move struct in memory. Usually this operation is transparent (all Go pointers will be updated automatically). But pointers in C memory to this struct will not be updated and program may crash/UB/... when tries to use it. Do not use this way.
Limited (medium) way:
Similar to previous, but with Go struct allocated in C memory:
Obj = (*T)(C.calloc(C.size_t(unsafe.Sizeof(T{}))))
In this case Obj can not be moved by Go runtime because it is in C memory. But now if Obj has pointers to Go memory (fields with *-variables, maps, slices, channels, function-pointers, ...) then this also may cause crash/UB/... This is because:
if there are no (other) Go pointers to the same variable (memory), then Go runtime thinks that this memory is free and can be reused,
or, if there is other Go pointer to same variable (memory), then Go can move this variable in memory.
So, use this way only if struct has no pointers to Go memory. Usually this means that struct contains only primitive fields (ints, floats, bool).
Right (and hard) way:
Assign id (of integer type for example) for each object of type T and pass this id into C. In exported callback you should convert id back to object. This is right way with no limitation, so this way may be used always. But this way requires to maintain some array/slice/map to convert between objects and ids. Moreover, this convertation may require some synchronization for thread-safe (so see sync.Mutex and sync.RWMutex).
Original answer:
Not best answer and has restrictions, but no other suggested. In my case I can pass additional data to register_callback. This data will be passed back to callback on each call. So I pass unsafe.Pointer(Obj) as data and use gateway function:
//export callback
func callback(data SomeType1C, additionalData unsafe.Pointer){
obj := (*T)(additionalData) // Get original Obj (pointer to instance of T)
dataGo := *(*SomeType1)(unsafe.Pointer(&data)) // Cast data from C to Go type
obj.M(dataGo)
}
and register it like this:
register_callback_with_data(callback, unsafe.Pointer(Obj));
PS: but still want to know how to do this better in general case (without additional data).

How do I use a lua_topointer when grabbing a closure from the stack?

So I've been trying to implement lua inside of nim using the C bindings and everything works fine except I don't know how to deal with lua functions being passed to my nim/c created procs/functions.
Lua code:
task("custom_task", function()
task("This is called from lua")
end)
Nim proc:
proc task*(state: lua.Pstate): cint {.cdecl.} =
var task_name : cstring
if lua.isstring(state, 1) == 1:
task_name = lua.tostring(state, cint(1))
if task_name != nil:
echo task_name
# this is triggered for the 2nd parameter
if lua.isfunction(state, 2) == true:
var test = lua.topointer(state, 2)
result = 1
So the lua api doesn't have a tofunction method, just a tocfunction, so it seems like the only way to grab that function is using topointer, but I can't figure out how to use it in nim. Any help is appreciated.
The value returned by lua_topointer is not intended to be used for anything but hasing or output/debugging. Citing the Lua manual:
There is no way to convert the pointer back to its original value.
Typically this function is used only for hashing and debug information.
So if you want to work with a lua function, you'll have to find a different way. My suggestion would be to store the function in the lua registry. The function can then be identified by the registry index and its lua_State.
The only problem with this approach is that you'll have to remember to remove the function from the registry. Otherwise it will never be garbage collected.
Alternatively, one could lua_dump the function, which is obviously a rather expensive operation.

eval in function scope (accessing function args)

Given:
abstract ABSGene
type NuGene <: Genetic.ABSGene
fqnn::ANN
dcqnn::ANN
score::Float32
end
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x->("mutate_copy(gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
ng = NuGene()
mutated_ng = mutate_copy(ng)
results in:
ERROR: gene not defined
in mutate_copy at none:4
If I just look at it as a string (prior to running parse and eval) it looks fine:
"NuGene(mutate_copy(gene.fqnn),mutate_copy(gene.dcqnn))"
However, eval doesn't seem to know about gene that has been passed into the mutate_copy function.
How do I access the gene argument that's been passed into the mutate copy?
I tried this:
function mutate_copy{T<:ABSGene}(gene::T)
all_fields_except_score = filter(x->x != :score, names(T))
all_fields_except_score = map(x-> ("mutate_copy($gene.$x)"),all_fields_except_score)
eval(parse("$(T)("*join(all_fields_except_score,",")*")"))
end
But that expands the gene in the string which is not what I want.
Don't use eval! In almost all cases, unless you really know what you're doing, you shouldn't be using eval. And in this case, eval simply won't work because it operates in the global (or module) scope and doesn't have access to the variables local to the function (like the argument gene).
While the code you posted isn't quite enough for a minimal working example, I can take a few guesses as to what you want to do here.
Instead of map(x->("mutate_copy(gene.$x)"),all_fields_except_score), you can dynamically look up the field name:
map(x->mutate_copy(gene.(x)), all_fields_except_score)
This is a special syntax that may eventually be replaced by getfield(gene, x). Either one will work right now, though.
And then instead of eval(parse("$(T)("*join(all_fields_except_score,",")*")")), call T directly and "splat" the field values:
T(all_fields_except_score...)
I think the field order should be stable through all those transforms, but it looks a pretty fragile (you're depending on the score being the last field, and all constructors to have their arguments in the same order as their fields). It looks like you're trying to perform a deepcopy sort of operation, but leaving the score field uninitialized. You could alternatively use Base's deepcopy and then recursively set the scores to zero.

Export Data from Matlab function into the global frame and default matlab arguments

I have two things that I would like to do with my matlab function. I have a function that will get data from a series of files. Say i have this file structure:
Number 1:
I would like to be able to have some selected variables in a function become globally accessible and persist after the function has completed. That is say i have the following function:
[] = function(directory)
b = read(directory)
struct c = (do some stuff with b)
somehow globalise c
end
I understand that you can have c = function(directory) and then pass a variable however i would not like to o this, i would rather that the variable c just persists in the global scope. Can this be done?
Number 2:
Is it possible for a matlab function to have default arguments. Lets take the function from above. What I want to do is to have the directory default as the current directory. For example if the following data structure exists:
MatlabMainFolder
-> MatlabFunctions
-> Data
The user should be able to run function in Data and it will use the Data directory.But should also be able to do function('../Data') from the MatlabFunctions directy for the same effect. Is this possible?
First:
I think the following should make a variable globally accessible from within the function:
[] = function(directory)
b = read(directory)
global c; <------
struct tmp = (do some stuff with b)
c = tmp; <------
end
Then, add global c in all other files where you want c to be available, before using it. I would recommend just using c = function... if at all possible, though.
As suggested by #Ben, assignin can also be used to assign a variable into a different workspace. That way, from a function, any variable can be assigned in the 'base' workspace, which is the workspace accessible by all other files too. In this case:
assignin('base','c',c)
will create a variable c in the base workspace, with the same value as c in the function file. (Add this line at the end of the function).
Second:
You could do something like this:
function(path)
if nargin<1
path = '../Data';
end
% do things with path
end
This way, if function is called without inputs, the default path ../Data will be used, otherwise, the path given as input will be used. nargin will be equal to the number of arguments that were given as input.
To 1) globals as well as asignin are often frowned upon. You could also use persistent
Pseudocode snippet:
function out=fun((directory)
persistent out
if isempty(out)
fill out
return out;
Or even handle objects in case you feel like going modern ;)
To 2): Read about doc InputParser - it's more work than in many other languages - but it's possible.

Store a Lua function?

Calling a Lua function from C is fairly straight forward but is there a way to store a Lua function somewhere for later use? I want to store user defined Lua functions passed to my C function for use on events, similar to how the Connect function works in wxLua.
check the registry (luaL_ref()). it manages a simple table that lets you store any Lua value (like the function), and refer to it from C by a simple integer.
Building on Javier's answer, Lua has a special universally-accessible table called the registry, accessible through the C API using the pseudo-index LUA_REGISTRYINDEX. You can use the luaL_ref function to store any Lua value you like in the registry (including Lua functions) and receive back an integer that can be used to refer to it from C:
// Assumes that the function you want to store is on the top of stack L
int function_index = luaL_ref(L, LUA_REGISTRYINDEX);
The easiest way to do this is for your function to take a "name" and the lua function text. Then you create a table in the interpreter (if it doesn't exist) and then store the function in the table using the named parameter.
In your app just keep hold of a list of function names tied to each event. When the event fires just call all the functions from your table whose key matches the names in the list.

Resources