gprossliner / cobj Goto Github PK
View Code? Open in Web Editor NEWcobj allows to implement interface based polymorphism in plain c in a simple, efficient and typesafe way
Home Page: http://gprossliner.github.io/cobj/
License: Other
cobj allows to implement interface based polymorphism in plain c in a simple, efficient and typesafe way
Home Page: http://gprossliner.github.io/cobj/
License: Other
In cobj, in order to call interface methods, you need a reference to that very interface, which is itself the result of a queryinterface call.
Consider providing a reference to each implemented interface for a object to be created initialized when an object is initialized.
So you always have to deal with objects and the corresponding interfaces. This makes using cobj harder then in should be, and results in more boilerplate code.
Example:
// init a class
myclass c;
myclass_initialize(&c);
// get references for "interface1" and "interface2", and call the foo function on them:
interface1 i1;
interface2 i2;
interface1_queryinterface(&c.object, &i1);
interface2_queryinterface(&c.object, &i2);
interface1_foo(&i1);
interface2_foo(&i2);
This could become much more readable by:
// init a class. The cobj generator emits a default reference to each implemented interface.
myclass c;
myclass_initialize(&c);
// call methods by using the default references:
interface1_foo(&c.interface1);
interface2_foo(&c.interface2);
As a result of this change, queryinterface may not be needed at all, but this will go into a new issue.
cobj currently uses the COUNTER macro, which is available as a GCC extension, to render named for the private" variables, in the class struct. This should be avoided.
When implementing the cobj files for a project, some code was not generated, which was expected to be so. The problem was like:
//class.h
#include "header.h"
...
#define COBJ_INTERFACE_IMPLEMENTATION_MODE
#include "interface.h"
#undef COBJ_INTERFACE_IMPLEMENTATION_MODE
So far everything looks ok, but what if "interface.h" uses a include-guard, and "header.h" includes "interface.h"?:
// header.h
#ifndef _HEADER_H_
#define _HEADER_H_
#include "interface.h"
#endif
//interface.h
#ifndef _INTERFACE_H_
#define _INTERFACE_H_
#define COBJ_INTERFACE_NAME interface
...
#include "cobj-interface-generator.h"
#endif
The result is, that "interface.h" is included at a time, where COBJ_INTERFACE_IMPLEMENTATION_MODE is not defined. Although it's included again in class.h, this is not effective, since the include guard (#ifndef _INTERFACE_H_
), prevents the header to be processed again.
This seems to be related to #8, but even if COBJ_INTERFACE_IMPLEMENTATION_MODE is changed to an automatic check, the order still matters.
coby no longer uses the .object_size in the any class_descriptor. Because it's just a sizeof(classname), it can easly be retrieved by anyone interested, so we should just drop it.
If you don't have the cobj directory in your include path directly, but include the generators by specifing a path (like #include "cobj-interface-generator.h"), GCC fails to include the files in the "private" folder.
In v2 default interfaces will be created for each object (see #10). So you access object.interface_name to get a reference.
Currently in v1, the public interface methods are rendered like:
void interface_name_foo(interface * reference)
So you need to pass pointer to the interface.
This could be changed to passing a copy of the reference:
void interface_name_foo(interface reference)
PROS:
CONT:
Decision is not finally...
Within the generated code, we use bool, but it's not included in cobj.h
When running the class-declaration-generator.h, a struct named class_parameters is generated, which is never used.
cobj needs to generate some code for a class implementing an interface, like the methodtable struct. This is currently enabled for an included header, if COBJ_INTERFACE_IMPLEMENTATION_MODE is defined.
This is causing trouble, because one .h file may included other .h files as dependencies, but they are not implemented in the given class.
A solution need to be implemented, that COBJ_INTERFACE_IMPLEMENTATION_MODE is not specified by the user, but that cobj does something like (pseudo-code):
#define COBJ_INTERFACE_IMPLEMENTATION_MODE COBJ_INTERACE_NAME exisits_in COBJ_CLASS_INTERFACES
This would lead to cleaner code anyway, because this symbol defines redundant data.
Classes have the possibility to signal the caller that the initialization has failed. In the samples, it's already a bool, but the current version of the generator generates a void method with an int * as it's arg.
Currently the cobj generator declare a function in the .h file of the interface, and the implementation is in the interface-registry file, like:
// in interface.h
int interface_foo(interface * self, int j);
// in interface_registry.c
int interface_foo(interface * self, int j)
{
return self->mt->foo(self->object, j);
}
This "forwarder" method could be inlined by the compiler, if the cobj generator would emit it with the "inline" keyword in the header. This would have this advantages:
cobj want to compile without warnings on gcc with -wall option. The current version of the generator warns about "requires rest arguments to be used" in the method generator.
This is similar to #8. The #define COBJ_IMPLEMENTATION_FILE works as long as you don't include any class-header in "another" implementation file. Simply because there is no "another", so cobj will render code for the "another" class.
cobj itself has no dependency to the value of the class_initialize method. cobj just returns whatever is returned from the initialize_impl method. It's up to the caller to check it or not, or to assign any semantic with the value.
Why change to bool?
If a method is declared without using a comma between the type and the name, like:
#define COBJ_INTERFACE_METHODS \
COBJ_INTERFACE_METHOD(void, set_options, gpio_pin_options options) \
it's very hard to diagnose, because of the following macro:
#define COBJPVT_GEN_METHOD_ARGS_SEPERATOR_1 #error "Invalid Method Signature"
Using an #error within a #define is not possible. It should use some static assertion, if possible, or remote it in total
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.