As part of preparing for my GSoC project mentored by @carandraug, I am working on finding a way to create a classdef entirely from C++.
I managed to put together some code to do exactly that:
classdef_poc.h (1.7 KB)
The function “create_tiffclass” defines a classdef with the name “Tiff” with a “counter” property, it also defines the class constructor and a “print” method. To do that, it needs an instance of the cdef_manager and an instance of the symbol table.
To execute this code, what I am doing currently is I am calling this function inside the constructor of the cdef_manager as this is where the meta classes of the languages are defined and there is an instance of the cdef_manager and an instance of the symbol table readily available.
But as I discussed with David, it would be a better idea to do this feature without modifying the internals of Octave by using an oct file. So, I am looking for some pointers on whether or not that is possible and what to try out to get it to work.
David mentioned that @jwe may have valuable input on this topic.
I don’t understand how your constructor is supposed to work. It appears to require the first argument to be a classdef object, but normally a classdef constructor is defined something like this:
function obj = myclass (data)
obj.data = data;
and so it takes some non-class arguments and creates a class object.
Also, I see that the Matlab docs say that the constructor and other parts of a classdef class definition must be defined in the classdef file (the one with the keyword “classdef” and the properties/methods/etc. blocks). There emay be a few reasons for that restriction, but I suppose the most important thing is that classdef constructors are called in a strange way with the output (
obj in the example above) already default constructed. I don’t see how you could do that in a MEX or oct file.
Other methods may be defined in separate files. Presumably, those files could be MEX files (or, for Octave, oct files).
I haven’t tried, so it may not currently be possible to define classdef methods in oct files in Octave, but we could fix that.
Would it be OK, at least for now, if we had to declare the classdef object and constructor in a .m file and then allow all the other methods to be defined in oct files?
Yes, exactly. I have this part documented but I forgot to add the documentation here. The way it works is when there is a constructor call, its method is not called directly but instead, an object is created and initialized with the class properties and their default values, and then this object is prepended to the argument list which is then passed to the constructor method that I defined. That is why I need to extract this object from the argument list and not create it myself. All other class methods receive the object prepended to their argument list as well. The constructor preprocessing can be found in cdef-class.cc file under the function “construct_object”.
This all assumes that the Octave parser can recognize that the function call is a constructor call by having the class name registered by calling “make_class” and having the constructor attached to the class by calling “install_method”.
So the way I see it, I can use oct files to define the class constructor as well as the methods but someone has to call “make_class” and “install_method” so Octave could know about the existence of a class and its methods.
Of course I could be wrong and there could be some other stuff that needs to be done so that Octave wouldn’t be able to differentiate between the two ways of defining a classsdef.
While this would be one thing less to worry about, I don’t think it will solve the whole problem as the defined methods won’t be attached to the class and we will have to create thin wrappers that call them which is what we were trying to avoid here, unless there is something I am missing.
This means that you have to register the constructor .oct file as somehow special so that it is called differently from other .oct files (with the first argument set to be the default constructed object). I’d rather avoid that extra complexity if possible.
You can write a classdef with method declarations only. Yes, this is some duplication, but it is already possible. Then each method can be in a .oct file. Since Octave already allows defining multiple ordinary functions in a single .oct file, maybe we can also allow that for classdef methods.
Then your classdef file would look something like this:
m_prop = 42;
## Constructor must be defined in classdef .m file
## but may call an external (.m or .oct) function to
## do the real work.
function obj = myclass (args, ...)
## Note: OBJ is already magically default constructed by Octave.
obj = __myclass_ctor__ (obj, args);
## Other methods may be declared here and defined
## in external @myclass/mymethod.m (or .oct) files.
## NOTE: Octave fails to parse these declarations now,
## but they don't appear to actually be required, so can
## be omitted for now. Does Matlab require them to find
## external classdef methods?
[outputs, ...] = mymethod (obj, args, ...);
I tried an example like this with external .m files and it works. I didn’t try with external .oct files.
AFAIK, this is already possible, if the class is defined in a
@ directory and method oct files are stored in the same directory. See the attached example.
@tst.zip (347.6 KB)