Closed chille closed 5 years ago
This is a side effect of a design issue that hasn't been fixed yet. In short, eel_get_current_moduledata() only works from within functions - not constructors.
The problem is that a constructor is a just a raw C function from the EEL VM's perspective, so it doesn't have the 'function' EEL_object, where the common.module pointer would be found. Unfortunately, a class doesn't have any real ties to a module (apart from optionally being added to the 'exports' table of one), so the information is just not there.
However, there is a similar mechanism for this: 'classdata'. Each classdef has a void * field that can be set with eel_set_classdata() as the class is registered. It should be possible to retrieve it from within a constructor with eel_get_classdata() after you've created the object. (Technically, it only needs the VM and the type ID, but it grabs the latter from the object, as that's more convenient in most use cases.)
I had a really hard time trying to figure out how to access the classdata from within the constructor. But just seconds before I was going to post this reply I found a new that worked out. However, it does not involve eel_get_classdata()
. I cut 'n pasted the code from it, and changed a few things to get it to work.
static EEL_xno test_construct(EEL_vm *vm, EEL_types type, EEL_value *initv, int initc, EEL_value *result) {
EEL_state *es = VMP->state;
EEL_classdef *cd1 = o2EEL_classdef(es->classes[type]);
ClassData *cd = (ClassData*)cd1->classdata;
}
Am I doing something wrong, is this a bug, or would it be a good idea to att a helper function or macro that does what I'm doing?
See the other non working examples: https://github.com/chille/eel/blob/classtest/examples/main2.c
EDIT: And BTW, the reason why I'm interested in the object orienting parts of EEL is that I already have an application written in C++. It would be nice to have an EEL API that is identical to my C++ classes. And as this is a realtime application EEL seems to be the best choice.
EDIT2: Removed the second question. I discovered it was just a bug in my code.
EDIT3: Another problem with the code above is that EEL_classdef contains a variable named typeid, which is a C++ operator, so e_class.h can not be included in a C++ project.
Indeed, looking up the classdata via the type ID is correct thing to do.
Using VMP is of course "internal stuff", and won't work against a normal install, as the e_* headers are not installed - and that's also why that field is still named 'typeid'. It's obviously not a great name, but that header is not supposed to be included by external code, so it shouldn't be a problem normally.
Anyway, eel_get_classdata() should probably just take a type ID instead of an object, so it can be used in this situation. No need to have both variants, and passing an object just to get the type ID from it is kind of silly.
On that note, that's probably the root of the problems you're having: You need to create an object of the class that the constructor is for, and pass that to eel_get_classdata(). A constructor is expected to do that (and set up "result" as a reference to that object), which is why eel_get_classdata() takes an object pointer in the first place; there will always be an object around when it's used. (Though one may well want to check some classdata stuff before deciding whether the create an instance, or fail...)
As for the variant using get_current_function(): That essentially has undefined behavior in this context! You need to pass an object of the class the constructor is for. get_current_function() returns a function, and since the 'function' class happens to have classdata (EEL_function_cd; internal VM stuff) you get a pointer to that, which is probably not what you want. :-)
There seems to be no way to pass data from the C function that registers a class with
eel_export_class()
to the constructor for the newly registered class.I do the following:
eel_create_module()
and give it a pointer to my moduledataeel_export_class()
and provide a function pointer to a constructorI expect the following result:
eel_get_current_moduledata()
from my class constructor it should return a pointer to the previously allocated moduledata.I get the following result:
main.c:
test.eel:
Output: