Using AVS/Express |
|
This chapter describes the shared libraries both in UNIX (shared libraries) and in Windows (DLLs).
You can build and run methods that are part of the main AVS/Express executable without having to close and restart AVS/Express. This allows you to build and test modules as you develop them without having to exit from AVS/Express. To do this you must build the modules in a library for which the "dyn_libs" property has been set.
In order to dynamically load methods while running AVS/Express, you make the following changes while writing modules:
You can then add the module and create the method template and parameter declarations in the library in the usual way. You compile and build the external library outside AVS/Express.
Setting the dyn_libs property on a library causes AVS/Express to exclude these libraries from the process build files. When the project is compiled, the methods in modules in the dyn_libs libraries appear as "unregistered." When you run a project executable in which AVS/Express encounters unregistered methods in libraries for which the dyn_libs property is set, AVS/Express uses the library path variable to look for the methods. When it finds the methods, AVS/Express loads the methods from the external library and executes them.
You must compose a makefile and build the shared library containing the methods outside of Express. Currently the makefile necessary to build the dynamic library (outside of the Express process build) is not generated automatically.
For platforms for which AVS/Express supports shared libraries, you can see the appropriate compile and link flags to use in your makefile by looking at the platform specific MACH_CFLAGS, MACH_FFLAGS, MACH_CXXFLAGS (for compiling) and DLFLAGS, etc. (for linking) found in include/$MACHINE/machinc.mk in the Express install directory.
For other platforms it might be necessary to look at compiler and loader help files and manual pages. It might also be helpful to look at the help files on the system dynamic loading commands themselves. The commands used by Express can be seen in the include/avs/port.h file by searching for DL_OPEN, etc.
After you have created the shared modules, use the following procedure to edit and reload the methods:
As above, AVS/Express will load and execute the new code
The dyn_libs property is a string list separated by whitespace specifying the name of the libraries that contain the method(s) to be invoked. You can set the dyn_libs property on a library using the Properties Editor (All Properties). The dyn_libs property can be set on an individual module, but the operating systems load only at the library level. In most cases, the best use of a library is as a collection of related methods that would be likely to be used together.
The dyn_libs property is referenced:
When the process is compiled, i.e. "base -comp_proc xxx" is run (either directly or via the Add Module/Object Editor), methods that are members of libraries with the dyn_libs property effect the code generation process in the following way:
As described above, when the Object Manager tries to run a method and finds that it is unregistered, it will look for the dyn_libs property on the library containing the method template. If dyn_libs is found, the Object Manager will use the library path variable to find and load the external library specified in the dyn_libs property, look up the function address for the method within it, and execute the method.
It is important that you use the dyn_libs when doing project generation for a project that uses C++ code. The name mangling performed by C++ compilers can confuse the logic that looks up functions in dynamic libraries, leading to errors about not being able to find or load functions. The dyn_libs property alters to project generation process so that this problem is avoided.
As an example, consider the WriteUCD project at the IAC. If you don't use the dyn_libs property, the generated header file will have declarations as follows (shown somewhat simplified).
However, the C++ compiler will generate function names that do not exactly match the function names as shown above. AVS/Express will look for a function called, e.g., "WriteUCD__update__stub", but the name in the dynamic library will not match.
With the dyn_libs property, the generated header file will have declarations as follows.
The extra 'extern "C"' declaration instructs the C++ compiler to not use name mangling when compiling these functions. As a result AVS/Express' dynamic loading logic should be able to successfully find the function.
With Release 4.0, the architecture of AVS/Express on the Windows platforms has been changed to move the core libraries from the executable express.exe, to a DLL file, express.dll.
The express.dll library includes the AVS/Express libraries that support the API's most commonly used in module methods. These include all the OM, OMX, OMF, FLD and FLDF functions, as well as the common ARR, FILE, ERR, MAT and EV utilities in the TOOL and WTOOL libraries.). In addition, some libraries on which the API libraries depend are also included in the DLL, namely COMM, XDR, and GDIF.
To take advantage of the express.dll, you build your modules as DLL programs external to AVS and reference the express.dll. Then, during development, you can modify, rebuild, and test your module dll without having to restart AVS/Express. For detailed instructions about how to develop modules using express.dll, see Writing Dynamically Loaded Modules In AVS/Express on page 11-9.
Within AVS/Express itself, the W3C (Web) library (Read_URL, ReadWebField and ReadWebGeom macros) and the Read/Write image libraries are implemented as DLL libraries that share express.dll with the main executable. The W3C library uses the Object Manager dynamic loading property, while the Read/Write image libraries use their own dynamic loading method.
AVS/Express' use of memory at start-up in Release 4.0 is larger than an equivalent statically linked version. All code within a DLL is loaded when it is first referenced, and express.exe implicitly loads express.dll and agx.dll at start up. The memory is used for the Import Address Table and other code overhead that is needed to support the DLL mechanism.
However, if you run multiple copies of the AVS/Express executable, there will be a saving in memory since the express processes can share the same instance of the express.dll.
The dynamic loading capability can also potentially lead to reduced memory usage because the DLL mechanism defers loading code for module methods until the first reference to the library.
If you are shipping an AVS/Express application you do not need to change your procedures for Release 4.0. AVS/Express installs the required express.dll file in runtime\bin\%MACHINE% and automatically copies it to the application directory when you save the application.
If you build your own DLLs, it is good practice to build them in the runtime\bin\%MACHINE% directory. However, you will need to copy your DLL files to the final runtime application directory. AVS/Express does not automatically copy them from the runtime directory.
If you save compiled project in AVS/Express, the following changes in your current use of AVS/Express are required by the introduction of the express.dll architecture:
Each of these changes is described in detail in the sections that follow.
These changes are necessary to allow the express executable in your projects to properly access the express.dll. You must make these changes even if you do not intend to write DLLs that are external to AVS/Express.
The AVS/Express core libraries that were formerly statically linked are now implicitly linked by referencing the import library for the express.dll (express.lib). After installing Release 4.0, you must recompile your source code to ensure that AVS/Express functions and global data are being correctly referenced.
If you use the express.mk file generated by AVS/Express, you must regenerate the project makefiles for all your existing projects. For example, run the command `base -gen-proc express -exit' in each project directory.
The Object Manager generates the appropriate express.mk makefile to reflect the changes in this release. You do not need to make any other changes to the regenerated makefile.
After you regenerate the express.mk make file, you must recompile your source code to ensure that AVS/Express functions and global data are being correctly referenced.
If you use a makefile you have written yourself or generated with another tool such as MS Developer Studio, you must remove references to the AVS/Express static libraries.
If you hand edit your existing 3.3 or 3.4 makefile, remove the following line:
and add the following references:
If you use DevStudio, follow these steps:
Some users maintain local copies of AVS/Express v files to preserve customizations they have made in the files. If your project has a local copy of the v files for the libraries included in express.dll that are not replaced when you regenerate the project, you must update your copies with the Release 4.0 version of these files. These libraries are FLD, FLDF, GDIF and WTOOL. Their respective v files are fld.v, fldf.v, gdif.v and templ.v.
In Release 4.0, these v files have been changed by the addition of a new property, "in_dll." This is an internal property, not for use by developers, that is used when AVS/Express generates the makefile express.mk. This property causes the makefile generator to exclude the libXXX.a string in the express .exe link command. If you are using an obsolete version of the v file, you will see an error from the linker when you try to build your project signalling a missing LIB*.a file.
If you are writing your own module methods, you should always use the include files that are supplied or generated by AVS/Express when you compile your module methods. This ensures that the compiler can resolve macro definitions, perform correct function prototype checking, and dereference global data correctly. If you use extern statements to resolve AVS/Express global dependencies, your application will not perform correctly.
Before using Release 4.0, replace any extern statements by including the appropriate AVS/Express header file. You must then recompile all your source code so that the compiler includes the correct dereferencing code for the data in the DLL. The results are unpredictable if this de-referencing is incorrect. Your program may access incorrect data, and there are no warnings from the compiler/linker that alert you to the problem.
The AVS/Express static library archive (*.a) files for libraries now included in express.dll are not part of this release. It is not possible to statically link express.exe with these archive files and have the resulting executable function correctly.
In order to dynamically load methods while running AVS/Express, you make the following changes while writing modules:
You can then add the module and create the method template and parameter declarations in the library in the usual way. You can use the same method attributes and properties as in previous releases, and AVS/Express generates source code as expected. You compile and build the external DLL library outside AVS/Express. You must write the make file and the supporting DEF file for your module library. See, Building the External DLL on page 11-11.
For more information about using libraries and managing processes, see Chapter 10, Projects and Processes.
For more information about adding methods to AVS/Express see Chapter 8, Developing Modules.
See also Loading Methods Dynamically (UNIX) on page 11-2 .
Setting the dyn_libs property on a library causes AVS/Express to exclude these libraries from the express process build files. When you compile the project, AVS/Express marks the methods in libraries with the dyn_libs property as "unregistered".
When you run the project executable and AVS/Express encounters these unregistered methods in libraries for which the dyn_libs property is set, AVS/Express explicitly loads the library DLL file listed in the dyn_libs property, looks up the module method within the DLL, and calls the function.
You build the DLL from the source code files generated by the AVS/Express Add Module wizard. However, you must write the makefile with which to build your DLL and a DEF file listing the definitions you want to export from the DLL. As of this release, AVS/Express does not automatically generate these files.
For a detailed example of how to build an AVS/Express module as an external DLL, see Example: Using an External DLL Method on page 11-12. The sample DEF file and make file for this example are included in the AVS/Express install directory in xp_dll/example/win32.
During development, you can edit and reload the DLL while running the express process by performing the following steps:
If you are working with a complicated network, you can remove all instances of the DLL modules, by saving your project application and then deleting the application from Express. You can then rebuild the DLLs, and then select File-> Load Application to load the application and reload the DLL modules' modified code.
The dyn_libs property is a string list separated by whitespace specifying the name of the DLL files that contain the method(s) to be invoked. You can set the dyn_libs property on a library using the Properties Editor (All Properties). The dyn_libs property can be set on an individual module, but the operating systems load only at the library level. In most cases, the best use of a library is as a collection of related methods that would be likely to be used together.
The dyn_libs property is referenced:
When you build the express process, methods that are members of libraries with the dyn_libs property effect the code generation process in the following way:
You build the express process either directly by using the command line command base -gen_proc or base_comp_proc in the project directory, or indirectly by selecting the Edit Source or Compile Process buttons in the Add Module wizard or the Project-> Edit Source, Project-> Compile, or Project-> Saved Compiled Project menu commands from the Network Editor menu bar.
As described above, when the Object Manager tries to run a method and finds that it is unregistered, it will look for the dyn_libs property on the library containing the method template. If dyn_libs is found, the Object Manager will use the library path variable to find and load the external library specified in the dyn_libs property, look up the function address for the method within it, and execute the method.
The following example, outlines the procedure for created a DLL library, `mymods', containing an OMX module named `adder.' that has been created in the AVS/Express user library, Workspace 1. When the module was created, the out_hdr_file attribute was set to xp_adder.h, and the out_src_file attribute was set to xp_adder.cxx.
Samples of the files created in this example, including the DEF file, mymods.def, and the make file. mymods.mak, are included in the AVS/Express install directory in xp_dll/example/win32.
The basic steps in the example are the following:
AVS/Express creates a new express directory named `dll_proj.'
You return to the Network Editor.
Executing this make file, builds the program mymods.dll. When you instance the adder module in AVS/Express, it calls the exported functions in mymod.dll.
You can now instance and use the adder module from Workspace 1 in AVS/Express. When the module method is executed, AVS/Express loads the mymods.dll and executes the update method there.
It is important that you use the dyn_libs when doing project generation for a project that uses C++ code. The name mangling performed by C++ compilers can confuse the logic that looks up functions in dynamic libraries, leading to errors about not being able to find or load functions. The dyn_libs property alters to project generation process so that this problem is avoided.
As an example, consider the WriteUCD project at the IAC. If you don't use the dyn_libs property, the generated header file will have declarations as follows (shown somewhat simplified).
However, the C++ compiler will generate function names that do not exactly match the function names as shown above. AVS/Express will look for a function called, e.g., "WriteUCD__update__stub", but the name in the dynamic library will not match.
With the dyn_libs property, the generated header file will have declarations as follows.
![]() |
![]() |
![]() |
![]() |