Embedding ODTK With C# and C++
In addition to invoking a full copy of ODTK application, you can now use a slimmed down version of the ODTK.Engine, but you still have the responsibility to initialize most of its environment yourself. The following examples show how to integrate the ODTK Engine into C# or C++ applications. Please contact AGI Technical Support for any additional questions.
C# Example
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ODTKEngLib; namespace ODTKEngTestCS { class Program { static void Main(string[] args) { Type oType = Type.GetTypeFromProgID("ODTK7.Engine"); //Type oType = Type.GetTypeFromProgID("ODTK7.Automation"); dynamic eng1 = Activator.CreateInstance(oType); eng1.Visible = false; eng1.UserControl = false; eng1.PrefFilesMode = AgEPrefFilesMode.ePrefFiles_NoLoad_NoSave; eng1.OpenLogFile(@"c:\temp\logCS.txt", AgEOpenLogFileMode.eOpenLogFileForWriting); eng1.LogMsg(AgEUiLogMsgType.eUiLogMsgInfo, "Hi"); eng1.LoadPersonality("ODTK.Engine"); dynamic ODTK = eng1.Personality; string userPath = ODTK.ApplicationPathUserData.value; dynamic ne = ODTK.Application.TrackingDataFileTypes.NewElem(); ne.Extensions = "geosc;geos;dat"; ne.PluginID = "IAgODProvideTrackingData7.AgODProvideGeoscTrackingData"; ODTK.Application.TrackingDataFileTypes.insert(ne); ne.Extensions = "gobs;s"; ne.PluginID = "IAgODProvideTrackingData7.AgODProvideGenericTrackingData"; ODTK.Application.TrackingDataFileTypes.insert(ne); dynamic res = (ODTK.Application.LoadObject("", @"c:\temp\Scenario1.sco")).Value; if (res == true) { dynamic scen = ODTK.Children.Scenario.Item(0); string scName = scen.name.Value; eng1.LogMsg(AgEUiLogMsgType.eUiLogMsgDebug, "scenName = " + scName); dynamic fil = scen.Filter.Item(0); dynamic res2 = fil.Go(); eng1.LogMsg(AgEUiLogMsgType.eUiLogMsgDebug, "filter.Go() returned = " + res2.value); ODTK.Application.DeleteObject(scen); } } } }
C++ Example
#define _CRT_SECURE_NO_WARNINGS #include#define _AFXDLL #include #include #include #include #include #import "C:\Program Files\AGI\ODTK 7\bin\ODTKEng.dll" int lAgFpieeeHandler(_FPIEEE_RECORD *pieee); #define X(expr) if( !(SUCCEEDED(expr)) ) exit(__LINE__) #define GetDD(DD,name,propDD) { VARIANT v; X(DD.GetPropertyByName(name,&v)); propDD.p = v.pdispVal; } #define GetVal(DD,name,propV) { CComDispatchDriver propDD; GetDD(DD,name,propDD); X(propDD.GetPropertyByName(L"value",propV)); } #define SetVal(DD,name,propV) { CComVariant vv(propV); X(DD.PutPropertyByName(name,&vv)); } #define ConvertRetVal(retVar) { CComDispatchDriver propDD; propDD.p = retVar.pdispVal; retVar.vt = VT_EMPTY; X(propDD.GetPropertyByName(L"value",&retVar)); } #define Iv0( DD,funcName) { DISPID funcID; X(DD.GetIDOfName(funcName,&funcID)); X(DD.Invoke0(funcID)); } #define Iv0r(DD,funcName,ret) { DISPID funcID; X(DD.GetIDOfName(funcName,&funcID)); X(DD.Invoke0(funcID,ret)); } #define Iv1( DD,funcName,a1) { DISPID funcID; CComVariant v1(a1); X(DD.GetIDOfName(funcName,&funcID)); X(DD.Invoke1(funcID,&v1)); } #define Iv1r(DD,funcName,a1,r) { DISPID funcID; CComVariant v1(a1); X(DD.GetIDOfName(funcName,&funcID)); X(DD.Invoke1(funcID,&v1,r)); } #define Iv2(DD,funcName,arg1,arg2) \ {DISPID funcID; CComVariant varg1(arg1), varg2(arg2);\ X(DD.GetIDOfName(funcName,&funcID));\ X(DD.Invoke2(funcID,&varg1,&varg2));\ } #define GetItem(DD,scopeName,i,itemDD) \ { CComDispatchDriver scopeDD;\ GetDD(DD,scopeName,scopeDD);\ VARIANT v; Iv1r(scopeDD, L"Item",i,&v); itemDD.p = v.pdispVal; } void run(void) { char str[128]; CComVariant v1; CComBSTR z, z2, z3; ODTKEngLib::IAgODTKEnginePtr eng1; CComDispatchDriver persDD, appDD, appChDD, scenDD, simDD, filDD, trkDD, neDD, rDD; X(CoInitialize(0)); X(eng1.CreateInstance("ODTK7.Engine")); //X(eng1->put_LoggingMode(eLogActive)); X(eng1->raw_OpenLogFile(L"c:\\temp\\log1.txt", ODTKEngLib::eOpenLogFileForWriting,&v1.boolVal)); eng1->raw_GetLicenseHostID(&z); eng1->get_Version(&z2); eng1->get_LogFile(&z3); X(eng1->raw_LogMsg(ODTKEngLib::eUiLogMsgDebug,z)); X(eng1->get_Personality(&persDD.p)); GetDD(persDD, L"Application", appDD ); GetDD(persDD, L"Children", appChDD ); GetDD(appDD, L"TrackingDataFileTypes", trkDD ); Iv0r(trkDD,L"NewElem",&v1); neDD = v1.pdispVal; SetVal(neDD,L"Extensions",L"geosc;geos;dat"); SetVal(neDD,L"PluginID",L"IAgODProvideTrackingData7.AgODProvideGeoscTrackingData"); Iv1(trkDD, L"insert", CComVariant(neDD.p)); SetVal(neDD, L"Extensions",L"gobs;s"); SetVal(neDD, L"PluginID", L"IAgODProvideTrackingData7.AgODProvideGenericTrackingData"); Iv1(trkDD, L"insert", CComVariant(neDD.p)); // // Assuming scenario has ready to run Simulator and Filter objects // Iv2(appDD,L"LoadObject",L"",L"c:\\temp\\Scenario1.sco"); GetVal(appChDD, L"size", &v1 ); sprintf_s(str,"#scenario loaded = %d", v1.intVal); X(eng1->LogMsg(ODTKEngLib::eUiLogMsgDebug,str)); GetItem(appChDD,L"Scenario", 0, scenDD); GetItem(scenDD, L"Simulator", 0, simDD); GetItem(scenDD, L"Filter", 0, filDD); Iv0r(simDD, L"Go", &v1); ConvertRetVal(v1); sprintf_s(str, "# simulator run successfully = %s", v1.boolVal != FALSE ? "true" : "false"); X(eng1->LogMsg(ODTKEngLib::eUiLogMsgDebug, str)); Iv0r(filDD, L"Go", &v1); ConvertRetVal(v1); sprintf_s(str, "# filter run successfully = %s", v1.boolVal != FALSE ? "true" : "false"); X(eng1->LogMsg(ODTKEngLib::eUiLogMsgDebug, str)); } int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow) { // By default all exceptions are masked. Value of the environment // variable determines which ones will be unmasked based on the // exception masks defined in float.h. _control87 is used rather // than _controlfp because it allows us to control the denormal // exceptions. // // for example, you could set the environment variable to any // combination of the following. A typical value to trap // zero divide or invalid numbers would be 0x18. // // _EM_INEXACT = 0x00000001 // _EM_UNDERFLOW = 0x00000002 // _EM_OVERFLOW = 0x00000004 // _EM_ZERODIVIDE = 0x00000008 // _EM_INVALID = 0x00000010 // _EM_DENORMAL = 0x00080000 unsigned int flag = 0x18; char *flagStr = getenv("AGI_FLOATING_POINT_EXCEPTIONS"); if (flagStr != NULL) { sscanf(flagStr, "%i", &flag); } // limit the possible values so you can't really // screw up the FP processor flag &= 0x0008001f; int cw = _control87( 0,0 ); _control87( cw & ~flag, MCW_EM ); SetProcessAffinityMask(GetCurrentProcess(), 0);//m_nProcAffinityMsk); __try { run(); } __except((_fpieee_flt(GetExceptionCode(), GetExceptionInformation(), lAgFpieeeHandler))) { } return 0; } int lAgFpieeeHandler(_FPIEEE_RECORD *pieee) { _clearfp(); char *sMessage = "Floating point arithmetic error."; if(pieee->Cause.ZeroDivide) { sMessage = "Division by zero."; } else if(pieee->Cause.InvalidOperation) { sMessage = "Invalid floating point operation."; } else if (pieee->Cause.Inexact) { sMessage = "Inexact result."; } else if (pieee->Cause.Underflow) { sMessage = "Underflow occurred."; } else if (pieee->Cause.Overflow) { sMessage = "Overflow occurred."; } else { sMessage = "An unknown floating point error occurred."; } fprintf(stderr, "FP exception caught: %s", sMessage); return EXCEPTION_CONTINUE_EXECUTION; }