Created
September 25, 2012 08:46
-
-
Save jamesu/3780691 to your computer and use it in GitHub Desktop.
Using the EngineAPI in Torque3D
This file contains hidden or 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
// Note you will need to create a "getFunctionAddress" function in EngineFunctionInfo unless you use | |
// getProcAddress() & getBindingName() on the function exports. | |
void *getFunctionAddress() { return mAddress; } | |
// | |
// This example demonstrates the following: | |
// * calling "generateUUID" which is exported as a global function in the API. | |
// * constructing an instance of ColorI and setting its exposed fields. | |
// | |
// Note that the idea behind engineAPI is that you load the Torque3D dll then enumerate the API | |
// information and create a native binding for it. Using the information, you can construct a | |
// representation of every type the API uses, as well as call functions and methods. | |
// | |
// From what I can tell it's not really meant to be used internally, which kind of makes | |
// sense considering you can just stick stuff on the end of the DefineEngine* macros to generate an | |
// internal binding for your favourite scripting language. | |
// | |
// For something more c-like there is the API in "cinterface/" which is a wrapper for the console | |
// API, though that doesn't use the engineAPI stuff. | |
// | |
#include "console/engineAPI.h" | |
// Alternate representation of Torque::UUID | |
// Size determined by EngineTypeInfo::getTypeInfoByName("UUID")->getInstanceSize(). | |
typedef struct TorqueUUID | |
{ | |
char data[16]; | |
} TorqueUUID; | |
// Alternate representation of ColorI | |
// It's best just to import "core/color.h" for this, but this is just an example. | |
typedef struct TorqueColorI | |
{ | |
U8 r,g,b,a; | |
} TorqueColorI; | |
// Prototype for generateUUID | |
typedef TorqueUUID(*TorqueGenerateUUIDFunc)(); | |
// Construct an instance of a type | |
// For simple types using the equivalent C++ class is probably a better idea, but this is just an example. | |
ConsoleFunction(testCreateEngineType, void, 1, 1, "") | |
{ | |
const EngineTypeInfo *colorTypeInfo = EngineTypeInfo::getTypeInfoByName("ColorI"); | |
U32 colorSize = colorTypeInfo->getInstanceSize(); | |
U32 structSize = sizeof(TorqueColorI); | |
Con::printf("EngineAPI ColorI size: %i, Struct size: %i", colorSize, structSize); | |
TorqueColorI col; | |
// Consruct the ColorI in col | |
if (colorTypeInfo->constructInstance(&col)) { | |
Con::printf("Created ColorI"); | |
// Enumerate the fields, set r,g,b,a to 0,1,2,3 | |
const EngineFieldTable *fieldTable = colorTypeInfo->getFieldTable(); | |
for (int i=0; i<fieldTable->getNumFields(); i++) { | |
const EngineFieldTable::Field field = (*fieldTable)[i]; | |
U8 *ptr = (U8*)(&col) + field.getOffset(); | |
*ptr = i; | |
Con::printf("Field: %s, Type == %s, Value == %i", field.getName(), field.getType()->getTypeName(), *ptr); | |
} | |
// Clean up instance | |
colorTypeInfo->destructInstance(&col); | |
} | |
} | |
// Enumerate the global function list, calling a function | |
ConsoleFunction(testCallEngineExport, void, 1, 1, "") | |
{ | |
EngineExport *currentExport; | |
EngineExportScope *exports = EngineExportScope::getGlobalScope(); | |
// First we need to initialize the engine API | |
engineAPI::gIsInitialized = true; | |
// Enumerate the root, only has 1 entry (the global scope) | |
for (currentExport = exports; currentExport; currentExport = currentExport->getNextExport()) { | |
const char *kindType = "Unknown"; | |
switch (currentExport->getExportKind()) { | |
case EngineExportKindScope: | |
kindType = "Scope"; | |
break; | |
case EngineExportKindFunction: | |
kindType = "Function"; | |
break; | |
case EngineExportKindType: | |
kindType = "Type"; | |
break; | |
} | |
Con::printf("Export: %s, Type=%s", currentExport->getExportName(), kindType); | |
// Check if this is a the global scope | |
EngineExportScope *scopeExport = dynamic_cast<EngineExportScope*>(currentExport); | |
if (!scopeExport) | |
continue; | |
// Enumerate the global scope. This contains global functions, classes, types, etc | |
for (EngineExport *subExport = scopeExport->getExports(); subExport; subExport = subExport->getNextExport()) { | |
// | |
const char *subKindType = "Unknown"; | |
switch (subExport->getExportKind()) { | |
case EngineExportKindScope: | |
subKindType = "Scope"; | |
break; | |
case EngineExportKindFunction: | |
subKindType = "Function"; | |
break; | |
case EngineExportKindType: | |
subKindType = "Type"; | |
break; | |
} | |
EngineTypeInfo *typeExport = dynamic_cast<EngineTypeInfo*>(currentExport); | |
Con::printf("Sub Export: %s, Type=%s", typeExport ? typeExport->getTypeName() : subExport->getExportName(), subKindType); | |
// If we encounter "generateUUID", call it | |
if (dStrcmp(subExport->getExportName(), "generateUUID") == 0) { | |
EngineFunctionInfo *funcExport = dynamic_cast<EngineFunctionInfo*>(subExport); | |
// Note: the intended method is to call getProcAddress() on funcExport->getBindingName(), | |
// but since we are doing this here we'll use a shortcut. | |
const EngineTypeInfo *type = EngineTypeInfo::getTypeInfoByName("UUID"); | |
Con::printf("UUID SIZE == %i, struct size == %i", type->getInstanceSize(), sizeof(TorqueUUID)); | |
// Call generateUUID with our TorqueUUID struct | |
TorqueGenerateUUIDFunc func = (TorqueGenerateUUIDFunc)funcExport->getFunctionAddress(); | |
TorqueUUID uuid = func(); | |
// Convert to a Torque::UUID and call toString() | |
TorqueUUID *uuidPtr = &uuid; | |
String uuidString = reinterpret_cast<Torque::UUID*>(uuidPtr)->toString(); | |
Con::printf("Generated UUID: %s", (const char*)uuidString); | |
// Stop so we can see the result | |
return; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment