New TlbImp Release on CodePlex – Full Customization of Interop Assemblies
It has been a few months since our last release of TlbImp on CodePlex. We recently released a new version of TlbImp – please visit the Codeplex page for this tool to find out more.
In this release, we’ve introduced two major features:
1. Ruled-based customization of interop assemblies
2. TlbImp regression test tool
Ruled-based customization of interop assemblies
The new TlbImp utility allows users to customize the interop assembly conversion process within TlbImp, by specifying a set of rules to customize specified types/functions/signature. We’ve received a lot of feedback from TlbImp users that they want the ability to make their own changes to the interop assembly in their build process, and they end up using ILDASM to disassemble the interop assembly into IL code, modify it using a PERL script, and then use ILASM to re-generate the interop assembly. This is obviously a painful process and requires a lot of additional work. This feature is designed to solve this problem.
Let’s start with a simple example: suppose we’d like to change the name of a certain type from an interop assembly. Let’s first double click to open TlbImpConfigFileEditor.exe to start the config file editor, and open the type library which contains the type we want to customize – let’s just use Samples\ChangeManaged\Name\ChangeManagedNameSimple.tlb to illustrate this:
The left pane shows every type/function/signature/field in that particular type library, while in the right pane, all the rules in the config file are displayed. All these rules tell TlbImp how to customize the interop assembly.
In order to change the name of IComparable interface, we need to create a rule. First, let’s drag the IComparable interface from the left pane to the right pane, and you will see the following dialog:
The dialog above is used to create a new rule, which tells TlbImp
1) What types/functions/signatures/fields are affected, and
2) What kind of customization will be done
In this dialog, we need to specify the corresponding Action to be ChangeManagedName by selecting ChangeManagedName in the drop down box, so that the name of types will be customized. After clicking OK, you’ll see a rule gets created in the right pane as follows (you’ll need to expand the rule node on your own):
The rule named “Change interface name” has a category of type, which means this rule applies to types only, not functions, not signatures. The condition node has a sub tree defining a set of conditions which specifies what types are affected by this rule. By selecting the Condition node (or its sub nodes), you’ll be able to see the corresponding expression in the bottom (read-only), which is NativeName Equal ‘IComparable. It means that any type that is named “IComparable” in the type library will be affected by this rule. Because we were dragging the IComparable interface node to the right side, the right set of conditions that match the interface is automatically generated for you. You can also modify the condition by yourself if you wish. Say we would like to add one restriction that the rule only applies to interfaces. Let’s click the <Empty> node under the And node, select TypeKind in the first dropdown box, Equal in the second dropdown box, interface in the third dropdown box.
The result is as follows:
Please note that the condition nodes are organized like an abstract syntax tree. Therefore, all the condition nodes under the ‘And’ node are basically ‘And’-ed together. You’ll see the corresponding expression in the bottom pane, as follows:
( NativeName Equal ‘IComparable’ ) And ( TypeKind Equal ‘Interface’)
When the condition part is done, we’ll need to specify how the customization will be done. In this case, we need to specify the new name of the type. Clicking on the New Name node under Action node, you’ll get the dialog below:
Enter the new name and click OK. The rule is now completed:
Let’s save it as ChangeInterfaceName.xml, and call TlbImp2.exe under command line. You’ll need to use the new /config switch to refer to the .xml file you’ve just saved (as highlighted in yellow).
After running tlbimp2, you can start ILDASM on the result interop assembly and see what it is like after it is customized:
You’ll see IComparable has been renamed to IMyInterface (as highlighted in yellow).
Besides the ChangeManagedName action, TlbImp also supports a few other actions. A full list of supported actions is as follows:
1. ChangeManagedName: Change the name of specified entity
2. ResolveTo: Resolve a type library type to another managed type. We already have people requesting this feature (http://clrinterop.codeplex.com/WorkItem/View.aspx?WorkItemId=2565)
3. AddAttribute: Add attribute on any type
4. PreserveSig: Apply preserveSig transformation to functions and add PreserveSig attribute
5. ConvertTo: Change function signature. You can use ConvertTo to change int * to an int array.
Every action has a corresponding example under the Samples directory. Please feel free to try out those examples if you are interested.
Regression Test Tool
In order to help developers to make sure his change doesn’t cause any regression, we’ve developed a simple regression test tool, which is available at the same project page:
This is the same tool we’ve been using internally for developing this new TlbImp release.
Download and unzip the .zip file, double click to launch TlbImpRegressionTestTool.exe under bin directory, and then navigate to the file menu and open the testcase.xml under testcase directory:
You can see there is a list of all the test cases in the main window. Before running these testcases, you need to tweak some settings: Select settings under the Run menu, and enter the exact location of TlbImp2.exe and WinDiff.exe, which is required during test execution.
Please note that you can use a different diff tool as long as the diff tool accepts two arguments and compare the diff between the two.
After you are done with the configuration, select Run All Testcases or Run Selected Testcases under the run menu to run the testcases:
This tool will execute the selected testcases one by one and change the status accordingly once the test finished execution. A green background means success, while a red background suggests failure. In the case of failure, you can double click on that row to open windiff (or your preferred diff tool) which compares the expected result (generated from a stable version of TlbImp) and the actual result (generated from the specified TlbImp in the configuration step).
And that’s it. Do try out these new features, and let us know what you think about this new TlbImp release. Feel free to leave comments either at this blog or directly at http://clrinterop.codeplex.com/.
– Yi Zhang,