{"id":18776286,"url":"https://github.com/jdolan/objectively","last_synced_at":"2025-04-13T09:31:57.072Z","repository":{"id":55834311,"uuid":"23492823","full_name":"jdolan/Objectively","owner":"jdolan","description":"Object oriented framework and core library for GNU C. Inspired by Objective-C. Zlib license.","archived":false,"fork":false,"pushed_at":"2024-07-07T16:43:07.000Z","size":13980,"stargazers_count":33,"open_issues_count":3,"forks_count":7,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-07-07T17:33:47.905Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdolan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-30T14:02:45.000Z","updated_at":"2024-07-07T16:43:10.000Z","dependencies_parsed_at":"2024-07-07T17:43:09.195Z","dependency_job_id":null,"html_url":"https://github.com/jdolan/Objectively","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdolan%2FObjectively","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdolan%2FObjectively/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdolan%2FObjectively/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdolan%2FObjectively/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdolan","download_url":"https://codeload.github.com/jdolan/Objectively/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223580547,"owners_count":17168635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T19:45:49.601Z","updated_at":"2024-11-07T19:45:52.131Z","avatar_url":"https://github.com/jdolan.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](http://ci.quetoo.org/buildStatus/icon?job=Objectively-Linux-x86_64)](http://ci.quetoo.org/job/Objectively-Linux-x86_64/)\n[![Zlib License](https://img.shields.io/badge/license-Zlib-brightgreen.svg)](https://opensource.org/licenses/Zlib)\n![This software is ALPHA](https://img.shields.io/badge/development_stage-BETA-green.svg)\n\nObjectively\n===\nUltra-lightweight object oriented framework for [GNU C](http://www.gnu.org/software/gnu-c-manual/).\n\n[Foundation](https://developer.apple.com/reference/foundation)-inspired [core library](http://jaydolan.com/projects/Objectively).\n\nZlib [license](./COPYING).\n\nAbout\n---\n Objectively is a cross-platform object oriented framework for the C programming language. Unlike [GObject](https://developer.gnome.org/gobject/stable/), Objectively is not a platform on which to build OO languages. Rather, Objectively provides rich OO semantics to enable object oriented programming directly in C. It is based on C99, but utilizes several GNU extensions, and therefore requires `gcc` or `clang`. While others may work, the following targets are actively supported:\n \n * GNU / Linux with GCC or Clang\n * macOS with GCC or Clang\n * [MinGW-w64](https://mingw-w64.org) cross compile\n * MinGW-w64 Windows native\n * Visual Studio 2015 or later with Clang\n\nFeatures\n---\n * Single inheritance through _starts-with_ structure composition\n * `Class` and instance methods with strongly typed interfaces\n * Automatic class loading and lifecycle management\n * Automatic memory management with reference counting\n * Unicode and multibyte character set `String` support\n * `Object` primitives for `Boole`, `Date`, `Null`, `Number`, `String`\n * Mutable and immutable collections variants such as `Array` and `MutableDictionary`\n * JSON parsing, marshaling and introspection with `JSONSerialization` and `JSONPath`\n * Low-level concurrency constructs such as `Lock`, `Condition`, and `Thread`\n * High-level concurrency with `Operation` and `OperationQueue`\n * Resource loading via Internet protocols with `URLSession` and `URLSessionTask`\n\nAdding Objectively to your project\n---\n\n1. Do the Autotools dance.\n\n```shell\nautoreconf -i; ./configure; make; sudo make install\n```\n\n2. Include the main header file in your source.\n\n```c\n#include \u003cObjectively.h\u003e\n```\n\n3. Use Objectively in your application.\n\n```c\nObject *obj = $(alloc(Object), init);\nprintf(\"%d\\n\", $(obj, hash));\nrelease(obj);\n````\n\n4. Compile and link with Objectively.\n\n```shell\ngcc `pkg-config --cflags --libs Objectively` -o myprogram *.c\n```\n\nDeclaring a custom type\n---\n\nTypes in Objectively are comprised of 3 components:\n\n1. The instance `struct`, beginning with the parent type, followed by the interface, and any instance variables.\n\n```c\n/**\n * @brief The Hello type.\n */\nstruct Hello {\n\n\t/**\n\t * @brief The parent.\n\t */\n\tObject object;\n\n\t/**\n\t * @brief The interface.\n\t */\n\tHelloInterface *interface;\n\n\t/**\n\t * @brief The greeting.\n\t */\n\tconst char *greeting;\n};\n```\n\n2. The interface `struct`, beginning with the parent interface, followed by any Class or instance methods.\n\n```c\n/**\n * @brief The Hello interface.\n */\nstruct HelloInterface {\n\n\t/**\n\t * @brief The parent.\n\t */\n\tObjectInterface objectInterface;\n\n\t/**\n\t * @static\n\t * @fn Hello *Hello::helloWithGreeting(const char *greeting)\n\t * @brief A factory method for instantiating Hello.\n\t * @param greeting The greeting.\n\t * @return A new Hello with the given `greeting`.\n\t * @memberof Hello\n\t */\n\tHello *(*helloWithGreeting)(const char *greeting);\n\n\t/**\n\t * @fn Hello *Hello::initWithGreeting(Hello *self, const char *greeting)\n\t * @brief Initializes this Hello with the given `greeting`.\n\t * @param self The Hello.\n\t * @param greeting The greeting.\n\t * @return The initialized Hello, or `NULL` on error.\n\t * @memberof Hello\n\t */\n\tHello *(*initWithGreeting)(Hello *self, const char *greeting);\n\n\t/**\n\t * @fn void Hello::sayHello(const Hello *self)\n\t * @brief Prints this Hello's greeting to the console.\n\t * @param self The Hello.\n\t * @memberof Hello\n\t */\n\tvoid (*sayHello)(const Hello *self);\n};\n```\n\n3) The Class archetype, serving to tie 1. and 2. together.\n\n```c\n/**\n * @fn Class *Hello::_Hello(void)\n * @brief The Hello archetype.\n * @return The Hello Class.\n * @memberof Hello\n */\nOBJECTIVELY_EXPORT Class *_Hello(void);\n```\n\nImplementing a type\n---\n\nTo implement a type, implement its instance and Class methods and Class initializer:\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003cObjectively.h\u003e\n\n#define _Class _Hello\n\n/**\n * @fn Hello *HelloInterface::helloWithGreeting(const char *greeting)\n * @memberof Hello\n */\nstatic Hello *helloWithGreeting(const char *greeting) {\n\treturn $(alloc(Hello), initWithGreeting, greeting);\n}\n\n/**\n * @fn Hello *HelloInterface::initWithGreeting(Hello *self, const char *greeting)\n * @memberof Hello\n */\nstatic Hello *initWithGreeting(Hello *self, const char *greeting) {\n\n\tself = (Hello *) super(Object, self, init);\n\tif (self) {\n\t\tself-\u003egreeting = greeting ? : \"Hello World!\";\n\t}\n\treturn self;\n}\n\n/**\n * @fn void HelloInterface::sayHello(const Hello *self)\n * @memberof Hello\n */\nstatic void sayHello(const Hello *self) {\n\tprintf(\"%s\\n\", self-\u003egreeting);\n}\n\n#pragma mark - Class lifecycle\n\n/**\n * @see Class::initialize(Class *)\n */\nstatic void initialize(Class *clazz) {\n \n\t((HelloInterface *) clazz-\u003einterface)-\u003ehelloWithGreeting = helloWithGreeting;\n\t((HelloInterface *) clazz-\u003einterface)-\u003einitWithGreeting = initWithGreeting;\n\t((HelloInterface *) clazz-\u003einterface)-\u003esayHello = sayHello;\n}\n\n/**\n * @fn Class *Hello::_Hello(void)\n * @memberof Hello\n */\nClass *_Hello(void) {\n\tstatic Class *clazz;\n\tstatic Once once;\n\n\tdo_once(\u0026once, {\n\t\tclazz = _initialize(\u0026(const ClassDef) {\n\t\t\t.name = \"Hello\",\n\t\t\t.superclass = _Object(),\n\t\t\t.instanceSize = sizeof(Hello),\n\t\t\t.interfaceOffset = offsetof(Hello, interface),\n\t\t\t.interfaceSize = sizeof(HelloInterface),\n\t\t\t.initialize = initialize\n\t\t});\n\t});\n \n\treturn clazz;\n};\n    \n#undef _Class\n```\n\nUsing a type\n---\n```c\nHello *hello = $(alloc(Hello), initWithGreeting, NULL);\n\n$(hello, sayHello);\n\nrelease(hello);\n```\nSee [Hello.h](Examples/Hello.h) and [Hello.c](Examples/Hello.c) for the full source to this example.\n\nInitialization\n---\nThere 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, its 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.\n\nInvoking an instance method\n---\nTo invoke an instance method, use the `$` macro.\n\n```c\n    $(condition, waitUntilDate, date);\n```\n\nInvoking a Class method\n---\nTo invoke a Class method, use the `$$` macro.\n\n```c\n    Dictionary *dict = $$(JSONSerialization, objectWithData, data);\n```\n\nOverriding a method\n---\nTo override a method, overwrite the function pointer from within your Class' `initialize` method.\n\n```c\n    ((ObjectInterface *) clazz-\u003einterface)-\u003edealloc = dealloc;\n    ((ObjectInterface *) clazz-\u003einterface)-\u003eisEqual = isEqual;\n```\n\nCalling super\n---\nTo invoke a supertype's method implementation, use the `super` macro.\n\n```c\n    super(Object, self, dealloc);\n```\n\nManaging memory\n---\nObjectively 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`.\n\nShared instances\n---\nA shared instance or _singleton pattern_ can be achieved through Class methods and _release-on-destroy_.\n\n```c\nstatic URLSession *_sharedInstance;\n\n/**\n * @fn URLSession *URLSessionInterface::sharedInstance(void)\n * @memberof URLSession\n */\nstatic *URLSession sharedInstance(void) {\n\tstatic Once once;\n\n\tdo_once(\u0026once, {\n\t\t_sharedInstance = $(alloc(URLSession), init);\n\t});\n\n\treturn _sharedInstance;\n}\n\n/**\n * @see Class::destroy(Class *)\n */\nstatic void destroy(Class *clazz) {\n\t_sharedInstance = release(_sharedInstance);\n}\n\n// ...\n\nURLSession *session = $$(URLSession, sharedInstance);\n```\n\nRemember to wire up the desctructor in your Class' initialization block. See [Once.h](Sources/Objectively/Once.h) for details on `do_once`.\n    \nExamples \u0026 projects using Objectively\n---\n\n1. The Hello example above can be seen [here](Examples/Hello.c).\n1. The [unit tests](Tests/Objectively) provide examples for using every Objectively class.\n1. [ObjectivelyMVC](https://github.com/jdolan/ObjectivelyMVC) is a cross-platform user interface and interaction framework for SDL2 and OpenGL built on Objectively.\n\n![ObjectivelyMVC](https://github.com/jdolan/ObjectivelyMVC/blob/master/Documentation/demo.gif)\n\nCode Templates\n---\nObjectively provides code templates for Xcode and Eclipse CDT that greatly cut down on the boilerplate required to declare and implement a type. These are _highly recommended_, as they will save you time and reduce errors in type declaration.\n\n#### Xcode\nInstall the Xcode code templates by simply building the Xcode project.\n\n![Objectively code templates in Xcode 8](Documentation/xcode-template-dialog.png)\n\n#### Eclipse CDT\nInstall the Eclipse CDT templates through the Eclipse CDT preferences:\n\n![Objectively code templates in Eclipse CDT](Documentation/eclipse-template-dialog.png)\n\nAPI documentation\n---\nThe API documentation can be [browsed online](http://jaydolan.com/projects/Objectively) or generated with [Doxygen](http://www.doxygen.org) by running `make html`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdolan%2Fobjectively","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdolan%2Fobjectively","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdolan%2Fobjectively/lists"}