Last active
May 29, 2017 13:43
-
-
Save ShonFrazier/16f46834355d9f6a28e3243497914142 to your computer and use it in GitHub Desktop.
Poco - Wrapping UUIDGenerator and UUID classes in C-friendly code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "PocoUUIDWrap.h" | |
int main(int argc, const char * argv[]) | |
{ | |
PocoUUIDGenerator *generator = PocoUUIDGeneratorCreate(); | |
PocoUUID *uuid = PocoUUIDGeneratorCreateRandom(generator); | |
const char *uuid_str = PocoUUIDToString(uuid); | |
printf("UUID: %s\n", uuid_str); | |
PocoUUIDFree(uuid); | |
uuid = NULL; | |
PocoUUIDGeneratorFree(generator); | |
generator = NULL; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "PocoUUIDWrap.h" | |
#include <Poco/UUID.h> | |
#include <Poco/UUIDGenerator.h> | |
using Poco::UUID; | |
using Poco::UUIDGenerator; | |
PocoUUID *PocoUUIDCreate(void) | |
{ | |
// Get the new object pointer... | |
UUID *_uuid = new UUID(); | |
// Cast it to the correct struct pointer type and return. | |
return (PocoUUID *)_uuid; | |
} | |
void PocoUUIDFree(PocoUUID *uuid) | |
{ | |
// Cast the struct pointer back to a C++ object pointer... | |
UUID *_uuid = (UUID *)uuid; | |
// ...and destroy it. The caller should set the variable to NULL to avoid accessing invalid memory. | |
delete _uuid; | |
} | |
const char *PocoUUIDToString(PocoUUID *uuid) | |
{ | |
// Cast to the C++ type... | |
UUID *_uuid = (UUID *)uuid; | |
// Return the C-string representation | |
return _uuid->toString().c_str(); | |
} | |
PocoUUIDGenerator *PocoUUIDGeneratorCreate(void) | |
{ | |
UUIDGenerator *_uuidGenerator = new UUIDGenerator(); | |
return (PocoUUIDGenerator *)_uuidGenerator; | |
} | |
void PocoUUIDGeneratorFree(PocoUUIDGenerator *uuidGenerator) | |
{ | |
UUIDGenerator *_uuidGenerator = (UUIDGenerator *)uuidGenerator; | |
delete _uuidGenerator; | |
} | |
PocoUUID *PocoUUIDGeneratorCreateRandom(PocoUUIDGenerator *uuidGenerator) | |
{ | |
UUIDGenerator *_uuidGenerator = (UUIDGenerator *)uuidGenerator; | |
UUID _uuid = _uuidGenerator->createRandom(); //Stack-allocated - DO NOT RETURN ADDRESS | |
// Make a new copy... | |
UUID *_puuid = new UUID(_uuid); | |
// ...and return THAT address, cast to the proper type. | |
return (PocoUUID *)_puuid; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PocoUUIDWrap_hpp | |
#define PocoUUIDWrap_hpp | |
#ifdef __cplusplus | |
// Make sure the (C++) compiler doesn't perform C++ name mangling on these symbols; "Use C linkage" | |
#define EXTERNC extern "C" | |
#else | |
// The C compiler already expects C linkage (actually specifying linkage is an error to a C compiler) | |
#define EXTERNC | |
#endif | |
// Because C has no concept of C++ objects, and because it's far too complex to create a complete | |
// struct to represent a C++ object ... | |
// Define opaque structs to represent our wrapped C++ objects. | |
EXTERNC typedef struct PocoUUID PocoUUID; | |
EXTERNC typedef struct PocoUUIDGenerator PocoUUIDGenerator; | |
// And because the structs are opaque, we have to work with pointers. Passing a copy of a *complete* | |
// struct type is possible, but we will never complete these structs. | |
// Ask for creation of a new UUID | |
EXTERNC PocoUUID *PocoUUIDCreate(void); | |
// Free a UUID | |
EXTERNC void PocoUUIDFree(PocoUUID *uuid); | |
// Get a C-string representation of a UUID | |
EXTERNC const char *PocoUUIDToString(PocoUUID *uuid); | |
// Ask for creation of a new UUIDGenerator | |
EXTERNC PocoUUIDGenerator *PocoUUIDGeneratorCreate(void); | |
// Free a UUIDGenerator | |
EXTERNC void PocoUUIDGeneratorFree(PocoUUIDGenerator *uuidGenerator); | |
// Generate a random UUID | |
EXTERNC PocoUUID *PocoUUIDGeneratorCreateRandom(PocoUUIDGenerator *uuidGenerator); | |
#endif /* PocoUUIDWrap_hpp */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To use a C++ class from C, wrap the classes and methods in C-friendly grammar: declare an opaque struct type to represent each class; allocate C++ objects with 'new', cast the pointer to a pointer to the opaque struct type, and return it; cast the struct pointer to the original class type to call methods on it; free with 'delete'; make sure to indicate C linkage on the new functions. In the code above, you'll also see returning a C-string instead of a std::string, as well as copying a stack-allocated object to a heap allocated object ('new') to avoid returning the address of a stack object.