gennet/gennet40 utility
WTSupported in traditional Synergy on Windows
|
|
|
|
The gennet/gennet40 utility generates Synergy classes that wrap the classes defined in a .NET assembly.
-
Use gennet with .NET Core and .NET 5 and higher. It is available as a .NET global tool from nuget.org.
-
Use gennet40 with .NET Framework. It is included with your Synergy/DE installation.
To generate wrappers for all classes in an assembly, use this syntax.
gennet|gennet40 -output output_file -log log_file assembly [assembly...]
To generate wrappers for specific classes in an assembly, use this syntax:
gennet|gennet40 -output output_file -log log_file -s xml_file [xml_file...]
Options
-output output_file
The path and filename of the generated Synergy source file. If an extension is not specified, .dbl will be added. You may use a full directory specification or an environment variable that contains a directory location. If output_file contains an environment variable (for example, MYDIR:myout.dbl), .INCLUDEs in the generated file will also use that environment variable. You can abbreviate -output to -o.
-log log_file
The path and filename of the generated log file. You can abbreviate -log to -l.
assembly
The names of one or more assemblies used for input. If assembly is contained in the GAC, do not specify a filename extension; in all other cases, you should include the extension. Assembly can be a full directory specification or an environment variable that contains a directory location. See Specifying an assembly in the Discussion for more information.
-s xml_file
An XML file that specifies individual classes within an assembly for which you want to generate wrappers. You can also specify a complete assembly in the XML file. See Specifying classes within an assembly (-s) in the Discussion for more information.
Discussion
Gennet/gennet40 generates wrappers for one or more .NET assemblies so you can use them in your Synergy applications.
Never run gennet/gennet40 twice for a single linked unit. If you run it twice and then link the resulting files together, a “Class CRC mismatch: class class name in module module name” error (CLSCRC) will occur. If you need to rerun gennet/gennet40, delete all the existing gennet/gennet40 output files first. |
Due to .NET security restrictions, gennet/gennet40 should not be run against DLLs over a network share.
Compilation time and memory usage can be significant for the wrapper routines generated by gennet/gennet40. For large assemblies and assemblies with a large number of dependencies (e.g., .NET Framework assemblies), consider using -s to limit processing to only the classes you will use. See Specifying classes within an assembly (-s).
To use gennet/gennet40 follow these steps:
1. | Run gennet or gennet40, specifying all of the assemblies (including dependent assemblies) that you want to use in your Synergy application. |
gennet -o gen_output.dbl MyAssembly.dll
This will produce at least two .dbl files (named gen_output.dbl, gen_output1.dbl, gen_output2.dbl, etc.) and an .inc file (gen_output.inc). The latter is no longer needed, but if your setup already uses it, you can continue to do so. The filename.dbl file will contain one or more .INCLUDE statements for the other, numbered .dbl file(s). The exact number of files generated depends on the amount of input. If the input is large, gennet/gennet40 breaks the output into multiple files.
See Restrictions and adaptations for information on how various aspects of class wrapper generation are handled.
2. | Prototype the generated file (the unnumbered one; gen_output.dbl in our example) using dblproto. See Synergy Prototype utility (dblproto) for more information. |
dblproto -out=proto_output.dbp gen_output.dbl
3. | Compile the Synergy output file that was created by gennet/gennet40 using -qrelaxed:interop to create a .dbo file. See Restrictions and adaptations for information on the requirement to use -qrelaxed:interop. |
dbl -qrelaxed:interop -o gen_output.dbo gen_output.dbl
Do not try to build a wrapper routine generated by gennet/gennet40 in debug mode. |
4. | Create a gen_output.elb file from the .dbo file you just created: |
dblink –l gen_output.elb gen_output.dbo
We recommend that you use OLBs for gennet/gennet40-generated classes when they are used in conjunction with ELBs that contain routines or methods that call the gennet/gennet40-generated classes. When linking an ELB with these OLBs, use the -r and -R switches.
5. | Compile your Synergy program that uses the wrappers. Make sure the compiler has access to prototypes generated in step 2. |
dbl –o MyProgram.dbo MyProgram.dbl
6. | Link in the .elb file you created in step 4 to your Synergy program and create a .dbr: |
dblink –o MyProgram.dbr MyProgram.dbo gen_ouput.elb
7. | Run your Synergy program: |
dbr MyProgram.dbr
If an assembly is loaded into gennet/gennet40 as a dependency and later at runtime has one of its types loaded before the original loading assembly, it will not be able to find the DLL outside of the GAC or the directory your program is running in. |
If assembly contains an environment variable (for example MYLOC:myassembly.dll) the generated wrapper will use that environment variable to load the assembly at runtime. Assemblies in the .NET global assembly cache (GAC) should not be specified with an environment variable. If neither an environment variable nor a physical path is specified, gennet/gennet40 searches for the assembly in the following order:
- The GAC (in .NET Framework 4x)
- The current directory
- The dbl\bin directory
- The windows\system32 directory
The gennet/gennet40 utility does not support search paths. If you specify an environment variable that is set to multiple directory paths, gennet/gennet40 will use only the first one.
If an assembly dependency fails to load from the GAC or the current gennet/gennet40 directory, gennet/gennet40 will try to load from each of the directories from which it has successfully loaded other assemblies. This list of directories is processed in order of appearance.
When running gennet/gennet40 on a DLL, the DLL filename and the assembly name must match. This restriction also applies to dependencies.
Specifying classes within an assembly (-s)
To specify a subset of the classes in an assembly, use the -s option. This option allows you to specify only the classes you want to build wrappers for, instead of creating a large number of unused classes. You do this by creating an XML file that specifies only the desired classes. Do not also specify assembly on the command line when you use the -s option; if you want to generate wrappers for all the classes in one assembly and only some of the classes in another assembly, specify both in the XML file.
Create an XML file with the following format:
<?xml version='1.0'?> <assemblies> <assembly Name="D:\test\MyClassLibrary.dll"> <class Name = "MyClassLibrary.Class2"/> <class Name = "MyClassLibrary.Class4"/> </assembly> <assembly Name="D:\test\YourClassLibrary.dll"> </assembly> </assemblies>
The resulting .dbl file will have wrappers for only Class2 and Class4 in MyClassLibrary and for all classes in YourClassLibrary.
Errors
Gennet/gennet40 may generate the following errors. In each of these cases, gennet/gennet40 will terminate with the error status and set the shell ErrorLevel to 1.
Error |
Cause |
---|---|
Cannot find specified Assembly name |
The specified assemblies cannot be opened and loaded as .NET assemblies. |
Error opening output/log file |
Output_file or log_file cannot be opened for output. |
As far as possible, the generated classes all have the same type information (methods, properties, fields, etc.) in Synergy/DE as they have in .NET, and they will use the DotNetObject methods described in Synergy .NET Assembly API to call their .NET equivalents.
Any features of .NET classes that cannot be emulated in Synergy/DE are omitted from the generated classes. Omitted features, types, and methods are reported in the log file. The following are known restrictions and adaptations:
- The -qrelaxed:interop compiler option is required when compiling wrapper classes because it truncates identifiers longer than 30 characters, which is the Synergy/DE limit. Gennet/gennet40 does not truncate identifiers, but it does detect any collisions resulting from the 30-character limit, omits entities involved in collisions, and logs these omissions to the log file. If a collision results in the omission of a class, methods and properties that require that class are also omitted.
- The classes generated by gennet/gennet40 are derived from DotNetObject, and a ToString() method with the NEW modifier is generated for each generated class. Whichever type your instance variable is declared as determines which ToString() will be used. Therefore, a call to ToString() will run DotNetObject’s ToString().
- Generics and class names containing invalid Synergy/DE identifier characters are not generated.
- An “m” is added to the beginning of any identifier that starts with a leading underscore (_) to make the name legal. Additionally, identifiers that are reserved words in Synergy classes (such as this, parent, and, or, etc.) are prefixed with “m_”.
- Interfaces are folded into the generated classes when possible but may present conflicts.
- Parameters and return values that collide with Synergy types in the System namespace are automatically converted to the Synergy type. If you are using System.Collections.ArrayList, modifications made to a returned array are not visible to the corresponding .NET object unless the array is copied back through a method or property invocation. In addition, delegates that have parameters defined as System.Collections.Arraylist are marked INOUT.
- Public members of System.Object that are not included in the Synergy implementation of System.Object are omitted from all generated classes.
- Any member that expects or returns a pointer type is omitted.
- All objects contain their full .NET constructors with parameters, including default constructors.
- Inheritance is flattened so all methods are visible.
- Reference parameters in the .NET assemblies are converted to INOUT arguments.
- An event is turned into a nested class. A member of that type is placed as an instance of the event, which allows you to use the AddHandler, RemoveHandler, and RaiseEvent methods. The nested class for the event is prefixed with “e_”.
- The Clone, Equals, CreateInstance, and GetObjectData methods are not generated on any generated classes.
See Synergy .NET Assembly API for more information.