Start a new topic

Accessing extensions from python script

Original Post by: dfoster2 Tue Jan 5 20:55:05 2016


I am trying to access extensions using OpenFlight python script.


For example, this command:


attr_count = ddGetExtFieldCount(code)


returns 0


I don't think that mgapilib.py can find the dll containing my extensions. I suspect it needs to be in a location relative to the directory containing mgapilib. I have tried putting the dll in that same directory, and have tried putting it in a subdirectory named plugins.


I can get this to work in C++ by having a plugins subdirectory containing the dll in the same directory as my executable, but I can't seem to make it work in Python.


Original Post by: SteveThompson Thu Jan 14 19:38:50 2016


I suspect you are on the right track. I believe your extension DLL is not getting loaded. Once it is loaded you should be able to query extension data as you are trying to do.


So lets focus on getting your extension DLL loaded into the stand alone python environment. Here is the text from the OpenFlight API Developer's guide on how stand alone program environments (C or Python) locate plugins:


Below is the directory search order for loading plug-in modules in the stand-alone program environment:

1 The directory (or directories) your program specifies when calling mgSetPluginFolder. If you call this function before mgInit to specify one or more directories, the folder(s) you specify will be searched for plug-ins. To specify more than one directory, pass a semi-colon delimited list of paths to mgSetPluginFolder.


2 The directory (or directories) specified by the environmental variable PRESAGIS_OPENFLIGHT_PLUGIN_DIR. This environmental variable may specify any accessible directory on your computer or may specify multiple directories using a semi-colon to delimit each path.


3 A directory named plugins immediately below the directory that contains the executable being run.

From what you suggest in your post you have figured out how to make rule 3 work. Try 1 or 2 and let us know what you find out.

Original Post by: dfoster2 Fri Jan 15 19:04:41 2016


I tried the three different methods, but couldn't get any of them to load my DLL.


My python executable is located at C:\Python27\python.exe


I created a directory at C:\Python27\plugins and put my plugin dll in it.


I created an environment variable named PRESAGIS_OPENFLIGHT_PLUGIN_DIR pointing to C:\Python27\plugins.


These are the commands I ran and the resulting messages:


>>> import mgapilib

>>> PRESAGIS_OPENFLIGHT_PLUGIN_DIR = "C:\\Python27\\plugins"

>>> mgapilib.mgSetPluginFolder(PRESAGIS_OPENFLIGHT_PLUGIN_DIR)

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

AttributeError: 'module' object has no attribute 'mgSetPluginFolder'

>>> mgapilib.mgInit(None, None)

I: OpenFlight API version 5.0.0.

I: Loading plugin <OpenFlight Data Dictionary> from <fltdata.dll>...

I: Site <FLTDATA> registered for plugin <OpenFlight Data Dictionary>.

I: Plugin <OpenFlight Data Dictionary> loaded

>>>


The mgSetPluginFolder command doesn't seem to be defined for version of the OpenFlight API I am using (version 13). I couldn't find it in the documentation either.


Even without the mgSetPluginFolder, I would think it should be able to locate the dll because it is in a plugins directory below my executable, and I also have the PRESAGIS_OPENFLIGHT_PLUGIN_DIR environment variable defined. I put the path to the plugins directory in my path environment variable as well.

Original Post by: SteveThompson Wed Feb 10 22:03:51 2016


Sorry for the long delay in response. We have not forgotten about you. Unfortunately I am out of the office this week so can't try the code you've posted in the API 5.0 (13) environment. Let me know if you are still having this problem and if so, I will be back in the office next Monday and I promise to take a look at this at that time.


Again, sorry for the long delay.

Original Post by: dfoster2 Thu Feb 11 14:06:13 2016


I still haven't been able to get this to work using python scripting. I can access my dll using the C++ API by having the plugins directory in the same directory as the executable, but my python script can't seem to locate the plugin directory. The plugin doesn't load.


I put my mgapilib directory that includes the mgapilib.py and all of the dlls into the python\Lib\site-packages directory with all of my other libraries. That works great until I try to access extensions. I created a plugins directory with my extensions dll in the same directory as my python.exe.


I must not have a version of the API that supports mgSetPluginFolder or the PRESAGIS_OPENFLIGHT_PLUGIN_DIR environment variable. I currently have Creator13, but may be able to get a more recent version if I need to.


I am thinking this is just some sort of configuration issue.


Thanks for following up.

Original Post by: SteveThompson Thu Feb 11 14:25:42 2016


I must not have a version of the API that supports mgSetPluginFolder or the PRESAGIS_OPENFLIGHT_PLUGIN_DIR environment variable. I currently have Creator13, but may be able to get a more recent version if I need to.

That is correct, mgSetPluginFolder is new for API 14. Same for PRESAGIS_OPENFLIGHT_PLUGIN_DIR, it's usage is new for API 14. Prior to that, plugins were loaded using PRESAGIS_CREATOR_PLUGIN_DIR.


If you stay with API 13, try PRESAGIS_CREATOR_PLUIGN_DIR. If you switch to 14, use the info in my previous message. Let me know if that does not work and I will fire up a test here when I get back in the office next week.


Sorry again for the delay.

Original Post by: SteveThompson Mon Feb 15 21:35:56 2016


Hi, we were able to run some tests in API environments 13, 14 and 15 and have some results to pass on to you regarding accessing your extensions from stand-alone scripts:


In API 13, if you set PRESAGIS_CREATOR_PLUGIN_DIR to the folder that contains your extension DLL, mgInit will load it in your stand-alone script.


In API 14 and later, you set PRESAGIS_OPENFLIGHT_PLUGIN_DIR not PRESAGIS_CREATOR_PLUGIN_DIR.


In all versions, adding a plugins folder to the folder containing the executable will only work for standalone programs, not standalone scripts. So adding a plugins folder to the python folder containing python.exe will not work. python.exe must be doing something strange to change the startup folder upon which mgInit depends.


There seems to be a bug in mgSetPluginFolder so we don't recommend using that until we can fix it.


To sum up, you will need to set the appropriate environment variable PRESAGIS_CREATOR_PLUGIN_DIR for API 13 or PRESAGIS_OPENFLIGHT_PLUGIN_DIR for API 14 in order for your extension DLLs to load properly.


Also note that if you are running your script from a Windows Command Shell, you must restart the shell if you change the environment variable from the Windows Control Panel. The shell makes a copy of the environment variables active when it starts and won't pick up any changes while it is active. Same thing for Visual Studio. This is a common gotcha you need to be careful about.


Finally once you get your extension DLL loaded properly, note that the symbols you have defined in the data dictionary for your attributes will not be recognized by Python. Unlike the OpenFlight Data Dictionary symbols like fltObject, fltPolyTexture, etc which are exported from the mgapilib python module for you, there is no such automatic export of these symbols if you run your script stand alone. You will need to somehow "define" these symbols in your script. Consider the following example:


You have defined a data extension whose site id is "MYDATA". In the data dictionary for your site you have defined an extension b]myObjFloat as a floating point number extension attached to an OpenFlight object node. To access this value on an object node in C, you would simply write:


float fVal;

numAttr = mgGetAttList (object, myObjFloat , &fVal;, MG_NULL);


or if you were writing this in your OpenFlight script inside of Creator:

numAttr,code,fVal = mgGetAttList (object, myObjFloat);


In C, myObjFloat is defined in the header file you build your code with.


In OpenFlight Script inside of Creator, myObjFloat is automatically defined for you by Creator in the python environment when Creator loads your extension.


The problem is outside of Creator (in your stand-alone script), the symbol myObjFloat is not known to Python. If you examine the header file you made for your extension you will notice how myObjFloat is defined:


#define myObjFloat (ddGetUCode(MY_SITEID, eMyObjFloat))


where MY_SITEID is defined as "MYDATA" and eMyObjFloat is an enum value.


If you want to use this symbol in your stand-alone script, you need to make this value known to Python somehow. The most straight-forward way to do this is to write the following in your script (before you try access the symbol):


MY_SITEID = "MYDATA"

myObjFloat = ddGetUCode(MY_SITEID, <number>)


where <number> is the integer value of the eMyObjFloat enum in your header file. This is easily calculated by counting its offset from the first enum.


You can repeat this process for each data extension symbol you need to access in your stand-alone script.


Sorry this may seem a little confusing. Please ask us if you have any questions. Let us know how you get on.

Login to post a comment