*** mingw port ***
yum -y install @c-development @development-tools wget mingw64-curl mingw64-libgnurx.noarch
git clone https://github.com/maci0/objectively.git
cd objectively
autoreconf -i
./configure --host=x86_64-w64-mingw32 --prefix=/usr/x86_64-w64-mingw32/sys-root/mingw/
Objectively
Ultra-lightweight object oriented framework for GNU C.
Foundation-inspired core library.
Zlib license.
Adding Objectively to your project
- Do the Autotools dance.
./configure; make; sudo make install
- Include the main header file in your source.
#include <Objectively.h>
- Compile and link with Objectively.
gcc `pkg-config --cflags --libs Objectively` -o myprogram *.c
Declaring a type
Types in Objectively are comprised of 3 components:
- The instance
struct
, beginning with the parent type, the type interface and then any additional instance variables.
/**
* @brief The Hello type.
*/
struct Hello {
/**
* @brief The parent.
*/
Object object;
/**
* @brief The typed interface.
*/
HelloInterface *interface;
/**
* @brief The greeting.
*/
const char *greeting;
};
- The interface
struct
, beginning with the parent interface, followed by any Class or instance methods.
/**
* @brief The Hello interface.
*/
struct HelloInterface {
/**
* @brief The parent.
*/
ObjectInterface objectInterface;
/**
* @brief A factory method for instantiating Hello.
*
* @return A new Hello with the given `greeting`.
*
* @relates Hello
*/
Hello *(*helloWithGreeting)(const char *greeting);
/**
* @brief Initializes this Hello with the given `greeting`.
*
* @return The initialized Hello, or `NULL` on error.
*
* @relates Hello
*/
Hello *(*initWithGreeting)(Hello *self, const char *greeting);
/**
* @brief Prints this Hello's greeting to the console.
*
* @relates Hello
*/
void (*sayHello)(const Hello *self);
};
- The class descriptor, serving to tie 1) and 2) together.
/**
* @brief The Hello Class.
*/
extern Class _Hello;
Implementing a type
To implement a type, implement its instance and Class methods and Class initializer:
#include <stdio.h>
#include <Objectively.h>
#define _Class _Hello
/**
* @see HelloInterface::helloWithGreeting(const char *)
*/
static Hello *helloWithGreeting(const char *greeting) {
return $(alloc(Hello), initWithGreeting, greeting);
}
/**
* @see HelloInterface::initWithGreeting(Hello *, const char *)
*/
static Hello *initWithGreeting(Hello *self, const char *greeting) {
self = (Hello *) super(Object, self, init);
if (self) {
self->greeting = greeting ? : "Hello World!";
}
return self;
}
/**
* @see HelloInterface::sayHello(const Hello *)
*/
static void sayHello(const Hello *self) {
printf("%s\n", self->greeting);
}
#pragma mark - Class lifecycle
/**
* @see Class::initialize(Class *)
*/
static void initialize(Class *clazz) {
HelloInterface *hello = (HelloInterface *) clazz->interface;
hello->helloWithGreeting = helloWithGreeting;
hello->initWithGreeting = initWithGreeting;
hello->sayHello = sayHello;
}
Class _Hello = {
.name = "Hello",
.superclass = &_Object,
.instanceSize = sizeof(Hello),
.interfaceOffset = offsetof(Hello, interface),
.interfaceSize = sizeof(HelloInterface),
.initialize = initialize,
};
#undef _Class
Using a type
Hello *hello = $$(Hello, helloWithGreeting, NULL);
$(hello, sayHello);
release(hello);
See Hello.c for the full source to this example.
Initialization
There is no explicit setup or teardown with Objectively. To instantiate a type, simply call alloc
from anywhere in your program. The first time a type is instantiated, an optional Class initializer, initialize
, is called. Use initialize
to setup your interface, override methods, or initialize a library your class wraps. When your application terminates, an optional Class destructor, destroy
, is also called.
Invoking an instance method
To invoke an instance method, use the $
macro.
$(condition, waitUntilDate, date);
Invoking a Class method
To invoke a Class method, use the $$
macro.
Dictionary *dict = $$(JSONSerialization, objectWithData, data);
Overriding a method
To override a method, overwrite the function pointer from within your Class' initialize
method.
((ObjectInterface *) clazz->interface)->dealloc = dealloc;
((ObjectInterface *) clazz->interface)->isEqual = isEqual;
Calling super
To invoke a supertype's method implementation, use the super
macro.
super(Object, self, dealloc);
Managing memory
Objectively uses reference counting to govern object retention. Newly instantiated Objects have a reference count of 1. To retain a strong reference to an Object, call retain(obj)
. To relinquish it, call release(obj)
. Once an Object's reference count reaches 0, it is deallocated. Remember to balance every retain
with a release
.
Shared instances
A shared instance or singleton pattern can be achieved through Class methods and release-on-destroy.
static URLSession *_sharedInstance;
/**
* @see URLSessionInterface::sharedInstance(void)
*/
static *URLSession sharedInstance(void) {
static Once once;
DispatchOnce(once, {
_sharedInstance = $(alloc(URLSession), init);
});
return _sharedInstance;
}
/**
* @see Class::destroy(Class *)
*/
static void destroy(Class *clazz) {
release(_sharedInstance);
}
// ...
URLSession *session = $$(URLSession, sharedInstance);
See Once.h for details on DispatchOnce
.
API documentation
The API documentation can be browsed online or generated with Doxygen by running make html
.