Cross-Language Interoperability
Language independence has a number of possible meanings. One meaning, which is discussed in the article Language Independence and Language-Independent Components, involves seamlessly consuming types written in one language from an app written in another language. A second meaning, which is the focus of this article, involves combining code written in multiple languages into a single .NET Framework assembly.
The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that includes two classes, NumericLib and StringLib. The NumericLib class is written in C#, and the StringLib class is written in Visual Basic. Here's the source code for StringUtil.vb, which includes a single member, ToTitleCase, in its StringLib class.
Imports System.Collections.Generic Imports System.Runtime.CompilerServices Public Module StringLib Private exclusions As List(Of String) Sub New() Dim words() As String = { "a", "an", "and", "of", "the" } exclusions = New List(Of String) exclusions.AddRange(words) End Sub <Extension()> _ Public Function ToTitleCase(title As String) As String Dim words() As String = title.Split() Dim result As String = String.Empty For ctr As Integer = 0 To words.Length - 1 Dim word As String = words(ctr) If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then result += word.Substring(0, 1).ToUpper() + _ word.Substring(1).ToLower() Else result += word.ToLower() End If If ctr <= words.Length - 1 Then result += " " End If Next Return result End Function End Module
Here's the source code for NumberUtil.cs, which defines a NumericLib class that has two members, IsEven and NearZero.
using System; public static class NumericLib { public static bool IsEven(this IConvertible number) { if (number is Byte || number is SByte || number is Int16 || number is UInt16 || number is Int32 || number is UInt32 || number is Int64) return ((long) number) % 2 == 0; else if (number is UInt64) return ((ulong) number) %2 == 0; else throw new NotSupportedException("IsEven called for a non-integer value."); } public static bool NearZero(double number) { return number < .00001; } }
To package the two classes in a single assembly, you must compile them into modules. To compile the Visual Basic source code file into a module, use this command:
vbc /t:module StringUtil.vb
For more information about the command-line syntax of the Visual Basic compiler, see Building from the Command Line (Visual Basic).
To compile the C# source code file into a module, use this command:
csc /t:module NumberUtil.cs
For more information about the command-line syntax of the C# compiler, see Command-line Building With csc.exe.
You then use the Link tool (Link.exe) to compile the two modules into an assembly:
link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll
The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Note that both the Visual Basic code and the C# code are able to access the methods in both classes.
To compile the Visual Basic code, use this command:
vbc example.vb /r:UtilityLib.dll
To compile with C#, change the name of the compiler from vbc to csc, and change the file extension from .vb to .cs:
csc example.cs /r:UtilityLib.dll
|
Title |
Description |
|---|---|
|
Explains how to create CLS-compliant software components that can be consumed by apps written in any language. |
|
|
Describes how types are declared, used, and managed by the common language runtime. |
|
|
Explains the common language runtime's mechanism for describing a type and storing that information with the type itself. |