Pushing a function from the global state into a Lua thread - api

I have a C++ function, called lua_tcall, which extends the abilities of lua_pcall. When lua_tcall is called, it expects that the top value of the stack is a Lua function, much like lua_pcall does. I would like lua_tcall to be able to create a thread, and use the function on the top of the global stack as the thread's function. How do I push the function from the global state into the lua_State* that I get back from lua_newthread?

To transfer values between states, lua_xmove is better than using a shared intermediary.

To transfer a function from one lua_State to another, you must use something global to both states to store the object as an intermediary. You could use a global variable or a registry entry.

Related

How do I require certain instance variables be provided at object creation?

Let's say I have a type of object in my game called oCharacter. All characters must have names, so I want to provide one when I construct the object. I can do that by using the _variables argument of instance_create_layer:
instance_create_layer(0, 0, "Instances", oCharacter, { name: "George" });
I could even make sure that I don't forget to do this by making a "constructor" function for characters and only instantiating them using that:
function character_create(_x, _y, _name) {
return instance_create_layer(_x, _y, "Instances", oCharacter, { name: _name });
}
But this approach has two problems.
The first is that I or another developer might forget about this convention and instantiate a character directly using instance_create_layer, forgetting to pass a name and setting up a runtime error further down the road.
The second (related) issue is that Feather doesn't know about this convention, so my Feather window is full of error messages about references to instance variables that aren't declared in the Create event - but I don't see how I can declare these variables in the Create event, as I'm expecting their value to be provided by the creator.
Is there some way of doing this that addresses these issues?
The first problem is just about setting rules about the code conventions within your team, if your team does not know about these conventions you want them to follow, then you should tell it them in a meeting.
For the second problem: Maybe you could create an empty/nullable variable in the Create Event? I'm afraid I'm not familiar with Feather
Personally I would do two things for this.
Create development standards for the team and put them in something like a Word document, wiki page, onenote, whatever makes the most sense for your team.
I would use a function to create the instance of the object (like you're doing there), and have some simple validation checks inside of the create event itself that will cancel it's creation (something like a guard clause) and output a debug message with a reminder.
It's not the most elegant solution but that should do the trick (assuming you haven't found something else by now haha)

Why do Env variables like signer_account_id cause error: ProhibitedInView?

I'm getting a ProhibitedInView error for a simple view function that does the following
export function getInfo(): Info {
const caller = context.sender
return infos.getSome(caller)
}
and realised that it's because of the context.sender call.
My assumption/understanding is that as long as a tx doesn't change the state, they can be considered ViewFunctions.
I found a warning against this on the Potential Gotchas, but why do the following functions cause view functions to fail? What does "binding methods that are exposed from nearcore" mean?
signer_account_id
signer_account_pk
predecessor_account_id
On the context of a view functions, there is no such thing as:
signer_account_id
signer_account_pk
predecessor_account_id
It is not required to sign any message to run a view function, and moreover it is not allowed. It is more like inspecting a contract anonymously, nothing should be paid for that, and the result is independent from the caller. Because of this there is no signer_account_id and signer_account_pk.
On the other hand, it is not possible to make a cross-contract call, if you are initiating this call in view mode. Because of this there is no predecessor_account_id available, since signer_account_id is not available, and it is impossible that this was called from another contract.

How one refers to an external global variable in Squeak FFI

For interfacing HDF5, I need to get a reference to/value of an external variable exported by the library, and pass it to other external functions.
For example, there is a variable representing the native double type: H5T_NATIVE_DOUBLE_g.
In VW, DLLCC, this is achievable thru a declarative annotation:
H5T_NATIVE_DOUBLE_g
<C: hid_t H5T_NATIVE_DOUBLE_g>
Is there anything similar in Squeak FFI? Is there any support for such use case?
After inquiry, there seem to be at least a basic support in the (Threaded)FFIPlugin:
ExternalAddress class>>loadSymbol: moduleSymbol module: module
<primitive: 'primitiveLoadSymbolFromModule' module: 'SqueakFFIPrims'>
^ self primitiveFailed
So we might create an ExternalData, get its address via above message (passing the global variable name and a given ExternalLibrary as module argument), and specify its type.
We can then use this ExternalData to pass the address if the external function expects a pointer.
To pass the value, one needs to dereference the address, not sure that it is automated by the plugin...
In my case, I know I will have to pass the value, so I may directly de-reference the address to get the value and store that (assuming that the global variable is assigned once at initialization and won't change afterward and assuming that initialization has already occured at library load time - lots of application specific assumptions...).

How can I pass a Perl 6 object through a Nativecall callback?

I'm working with the NativeCall interface.
The library is going to call my callback function a bunch of times.
That works fine. I can just declare my callback with the right
signature, pass it in as &callback and the library calls the sub just
fine.
It also has the capability to set a payload void *pointer to anything
I want, and it will include that in the call to my callback function.
Can I hide a Perl Str, for example, in the payload and successfully round trip it?
sub set_userdata(Pointer) returns int32 is native { ... }
sub set_callback(&callback(Pointer $userdata --> int32)) returns int32 is native { ... }
sub callback(Pointer $userdata) returns int32 {
my Str $mystring = ???
...
}
my Str $my-userdata-string;
set_userdata(???);
set_callback(&callback);
It seems like it could work with some incantation of binding, "is rw", nativecast() and/or .deref.
You can only use a native representation in such a case (such as CStruct, CArray, and CPointer), or alternatively a Blob. You are also responsible for ensuring that you keep a reference to the thing you pass as userdata alive from Perl 6's perspective also, so the GC doesn't reclaim the memory that was passed to the C function.
Memory management is the reason you can't pass any old Perl 6 object off to a C function: there's no way for the GC to know whether the object is still reachable through some C data structure it can't introspect. In a VM like MoarVM objects are moved around in memory over time as part of the garbage collection process also, meaning that the C code could end up with an out-dated pointer.
An alternative strategy is not not pass a pointer at all, but instead pass an integer and use that to index into an array of objects. (That's how the libuv binding inside of MoarVM tracks down the VM-level callbacks, fwiw.)
I got around this by just ignoring the userdata and making a new closure referencing the Perl object directly for every callback function. Since there is a new closure created every time I set the callback, I think this will leak memory over time.

Global variable initialization & finalization

I have a critical section that is shared between two threads:
TCriticalSection lock_measDataBuff;
I have declared this variable as global. Now because Delphi style classes must be constructed using operator new, i have modified above declaration as follows:
TCriticalSection *lock_measDataBuff;
Where is the best place to initialize the lock variable using operator new? Where is the best place to finalize the global variable using operator delete? Should it be WinMain method? Constructor of one of the classes accessing lock variable? Or some other place in the code?
I would use std::auto_ptr or boost::unique_ptr to handle all of that for you, eg:
#include <memory>
std::auto_ptr<TCriticalSection> lock_measDataBuff(new TCriticalSection);
As you are creating a global variable, you will need to initialize before you create the threads, which would be main, and the best place to release the memory would be after the threads end