1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN">
4 <meta http-equiv=
"content-type"
5 content=
"text/html; charset=ISO-8859-1">
6 <title>Convert Gecko from unmanged to managed code in .Net
</title>
9 <h1 style=
"margin-left: 40px; text-align: center;">Wrapping Gecko APIs
10 using Microsoft Visual Studio .NET Managed Extensions for C++
<big><big><big><br
11 style=
"color: rgb(255, 0, 0);">
12 </big></big></big> </h1>
13 <div style=
"text-align: center;"> <big><big><big><span
14 style=
"color: rgb(255, 0, 0);">**DRAFT**
</span></big></big></big><br>
17 <h2>Intended Audience:
</h2>
18 This paper is intended for a C++ programmer who would like to know how
19 to wrap Gecko engine from unmanaged C++ to managed C++ .
Author
20 assumes the reader is familiar with Gecko and MS Visual Studio.NET with
21 Managed Extensions for C++.
<br>
25 <li> Why do we go all this trouble?
</li>
26 <li>When we have Gecko as ActiveX control, then why don't we use the
27 Runtime-Callable Wrapper (RCW) and COM-Callable Wrapper (CCW)?
</li>
30 <h2 class=
"dtH1">How do we do this?
</h2>
31 There are few ways to convert the existing unmanaged code to managed
34 <li>You can use the built-in .NET runtime interop facilities (such as
35 PInvoke or COM Interop)
<br>
37 <li>You can wrap the unmanaged code using the managed extensions to
39 <li>You can rewrite the entire code in a .NET language.
</li>
41 <h2 class=
"dtH1">What do we need?
</h2>
44 <li>.NET Framework (
1.1)
<br>
46 <li>Microsoft Visual Studio .NET (preferably
2003)
</li>
47 <li>mozilla development environment
48 (http://www.mozilla.org/build/win32.html)
<br>
52 Following terms are used throughout out this document and it is
53 important to understand what each term means.
<br>
55 <li><span style=
"font-weight: bold;">Assembly
</span><br>
58 <div style=
"margin-left: 80px;">Assembly is a building block of the
59 .Net Framework.
It is the fundamental unit of deployment, version
60 control, reuse, activation, scoping, and security permissions.
It
61 provides the Common Language Runtime (CLR) with the information it needs
62 to be aware of type implementations.
It is a collection of types
63 and resources that are built to work together and form a logical unit of
64 functionality.
<br>
66 <ul style=
"font-weight: bold;">
67 <li>Global Assembly Cache
</li>
69 <div style=
"margin-left: 80px;">Global Assembly Cache is a machine wide
70 code cache that is installed whereever the CLR is installed.
In
71 most cases, if you intend to share an assembly with multiple
72 applications, you should deploy it into the global assembly cache.
<br>
75 <li><span style=
"font-weight: bold;">Managed code vs Unmanaged code
</span><br>
78 <div style=
"margin-left: 80px;"><span style=
"font-style: italic;">Manged
79 code
</span> requires the execution environment of the CLR.
80 Compilers emit managed code as MSIL, the intermidate language.
The
81 reason for the name is that code is managed by the CLR and objects are
82 allocated from heaps managed by the CLR.
<br>
84 <div style=
"margin-left: 80px;"><span style=
"font-style: italic;">Unmanaged
85 code
</span> does not use nor require the execution environment of the
86 Common Language Runtime (CLR).
Unmanaged code is outside the
87 reach of the CLR's security system, garbage collector and other
90 <li style=
"font-weight: bold;">CLR
</li>
91 <li style=
"font-weight: bold;">Runtime-Callable Wrapper (RCW)
</li>
92 <li style=
"font-weight: bold;">COM-Callable Wrapper (CCW)
</li>
93 <li style=
"font-weight: bold;">Boxing
</li>
95 <div style=
"margin-left: 80px;">Boxing is a technique to convert a
96 value type to a __gc object by using the __box
<br>
97 <div style=
"margin-left: 40px;">Int32 i =
42;
<br>
98 __box Int32* b = __box(i);
<br>
102 <li style=
"font-weight: bold;">UnBoxing
</li>
104 <div style=
"margin-left: 80px;">UnBoxing (dereferencing) is a technique
105 to convert a boxed object to value type by casting.
<br>
106 <div style=
"margin-left: 40px;">Color red;
<br>
107 Object* obj = Enum::Parse(__typeof(Color), S
"red");
<br>
108 red = *static_cast
<__box Color*
>(obj);
<br>
113 <li style=
"font-weight: bold;">Managed Objects
</li>
115 <div style=
"margin-left: 80px;">Managed Object is an instance of a
116 class which is created in the heap and managed by the garbage collector
117 by using the
<span style=
"font-style: italic;">__gc
</span>
119 <div style=
"margin-left: 40px;"><span style=
"font-style: italic;">__gc
</span>
123 <div style=
"margin-left: 80px;">public:
<br>
125 <div style=
"margin-left: 120px;"> int x;
<br>
128 <div style=
"margin-left: 40px;"> };
<br>
131 <ul style=
"font-weight: bold;">
134 <div style=
"margin-left: 80px;">Value Types ar typically small, short
135 lived objects and they are usually created on the stack. In managed C++,
136 the value types are defined by using
<span style=
"font-style: italic;">__value
</span>
138 <div style=
"margin-left: 40px;"><span style=
"font-style: italic;">__value
</span>
142 <div style=
"margin-left: 80px;">public:
<br>
144 <div style=
"margin-left: 120px;"> int x;
<br>
147 <div style=
"margin-left: 40px;"> };
<br>
151 <h2>Necessary Steps:
</h2>
156 We will be exposing list of Gecko APIs
<br>
158 <li>nsresult NS_InitEmbedding(nsILocalFile *aMozBinDirectory,
159 nsIDirectoryServiceProvider *aAppFileLocProvider);
<br>
161 <li>nsresult NS_TermEmbedding();
</li>
166 <h2>Coding Techniques:
</h2>
169 <h3>Using managed object in unmanaged code
</h3>
172 <div style=
"margin-left: 40px;">Managed pointers are managed by the
173 garbage collector so that when copies are made, the gc knows that
174 references are created.
When a pointer is passed to native code,
175 the gc cannot track its usage and so cannot determine any change in
176 object reference.
Furthermore, if a garbage collection
177 occures, the object can be moved in memory, so the gc changes all
178 managed pointers so that they point to the new location.
Because
179 the gc doesn't have access to the pointers passed to native code
180 (unmanaged code), potentially a pointer used in native code could
181 suddenly become invalid.
Use a pinned pointer which tells gc not
182 to move the memory.
<br>
183 <div style=
"margin-left: 80px;">
184 <table cellpadding=
"2" cellspacing=
"2" border=
"1"
185 style=
"text-align: left; width: 100%;">
188 <td style=
"vertical-align: top;">//Using pinning
<br>
189 #progma unmanaged
<br>
190 void print(int *p)
<br>
192 printf(
"%ld\n", *p);
<br>
196 _gc struct Test {
<br>
197 int i;
<br>
202 Test * t = new Test;
<br>
203 int __pin* p =
&t-
>i;
<br>
204 print(p);
<br>
212 <div style=
"margin-left: 40px;"><br>
216 <h3>Using unmanaged object in managed code
</h3>
219 <div style=
"margin-left: 120px;">
220 <table cellpadding=
"2" cellspacing=
"2" border=
"1"
221 style=
"text-align: left; width: 100%;">
224 <td style=
"vertical-align: top;"><span class=
"clsCap">//Using
226 <pre>#using
<mscorlib.dll
><br><br>using namespace System;
<br>using namespace System::Runtime::InteropServices;
<br><br>#pragma managed
<br>class AppDomainWrapper
<br>{
<br>private:
<br> int m_handle;
<br>public:
<br> AppDomainWrapper() {
<br> AppDomain* d = AppDomain::Current;
<br> m_handle = (GCHandle::op_Explicit(GCHandle::Alloc(d))).ToInt32();
<br> }
<br> ~AppDomainWrapper() {
<br> (GCHandle::op_Explicit(m_handle)).Free();
<br> }
<br> // more functions here...
<br> void PrintBaseDir() {
<br> AppDomain* domain = __try_cast
<AppDomain*
>(
<br> (GCHandle::op_Explicit(m_handle)).Target);
<br> Console::WriteLine ( S
"AppDomain Base Directory: {0}",
<br> domain-
>BaseDirectory );
<br> }
<br>};
<br><br>#pragma unmanaged
<br>int main() {
<br> AppDomainWrapper w;
<br> w.PrintBaseDir();
<br> return
0;
<br>}
</pre>
228 <td style=
"vertical-align: top;"><span class=
"clsCap">//Using
230 <pre>#using
<mscorlib.dll
><br>#include
<gcroot.h
><br><br>using namespace System;
<br>using namespace System::Runtime::InteropServices;
<br><br>#pragma managed
<br>class AppDomainWrapper
<br>{
<br>private:
<br> gcroot
<AppDomain*
> m_domain;
<br>public:
<br> AppDomainWrapper() {
<br> m_domain = AppDomain::CurrentDomain;
<br> }
<br> ~AppDomainWrapper() {
<br> }
<br> // more functions here...
<br> void PrintBaseDir() {
<br> Console::WriteLine ( S
"AppDomain Base Directory: {0}",
<br> m_domain-
>BaseDirectory );
<br> }
<br>};
<br><br>#pragma unmanaged
<br>int main() {
<br> AppDomainWrapper w;
<br> w.PrintBaseDir();
<br> return
0;
<br><br><br><br>}
</pre>
235 <span class=
"clsFigure"></span><span class=
"clsCap"></span> </div>
236 <h2>Useful Tools:
</h2>
238 <li>Viewing Assembly Contents
</li>
240 <li>MSIL Disassembler (ildasm.exe)
<br>
252 <h2 class=
"dtH1">References
<br>
255 <li>Visual Studio .NET
256 (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsintro7/html/vsstartpage.asp)
<br>
258 <li>Managed Extensions for C++ programming (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmex/html/vcconmcoverview.asp)
</li>
259 <li>Managed Extensions for C++ specifications
260 (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmxspec/html/vcManagedExtensionsSpec_Start.asp)
<br>
266 Draft
0.1 : April
9 2003 Roy Yokoyama
<br>