Upload
ashlynn-murphy
View
217
Download
0
Tags:
Embed Size (px)
Citation preview
DEV 420 Head-Spinning C++ Managed-Native Interoperability
Kate Gregory
Gregory Consulting
Too Much Choice?
Millions of lines of C++ code already existBusiness logic
Proprietary algorithms
Class libraries from long-dead vendors
This code is not going anywhereIt’s tested
It works
It’s paid for
Session Prerequisites
Familiarity with the .NET Framework and the CLR
Experience developing in Managed C++
Experience developing in unmanaged C++MFC
ATL
Another compiler or class library
Familiarity with COM concepts
Agenda
Setting the stageCOM InteropPInvokeIt Just WorksWhat should you do?
The Legacy
class ArithmeticClass{public:
double Add( double num1, double num2);
};
Unmanaged application
int _tmain(void){ArithmeticClass arith;cout << "1 + 2 is " << arith.Add(1,2) << endl;
return 0;}
Making the Legacy Available
You’re writing a new Managed C++ application
Or a VB.NET or C# application and you don’t mind it having some Managed C++ portions
You want to use your legacy library
You know there are tradeoffsYour effort
Performance
What else?
COM Interop
Managed code can use a COM component as simply as a .NET object
Runtime Callable Wrapper (RCW) looks like a .NET object on the outside, but inside it uses a COM component
Holds GUIDs, progids etc
Translates casts into QueryInterface, new into CoCreateInstance, etc
Handles reference counting
Can be generated automatically since a type library can map to an assembly’s metadata
How do you make an RCW?
From Managed C++ project, add a reference
Use the COM tab
Produces a passable RCW automaticallyMarshals between COM and .NET types
Handles QI and Reference Counting
Turns HRESULTs into exceptions
It is possible to write your own “Interop Assembly” if you really need to
Wrap the Legacy in COM
ATL ProjectAdd Simple ATL Object
Retype method definitions into wizardPaste method bodies into project
Could create a wrapper that called into a LIB or DLL
Using the COM Object#import "..\ComArithmetic\Debug\ComArithmetic.dll"
no_namespace
int _tmain(int argc, _TCHAR* argv[]){
::CoInitialize(NULL);//braces for scope only{IArithmeticClassPtr arith("ComArithmetic.ArithmeticClass");double answer = arith->Add(1,3);cout << "1 + 3 is " << answer << endl;cin.get();}::CoUninitialize();return 0;
}
Using COM from .NET
int _tmain(void){
ComArithmetic::CArithmeticClassClass*arith = new
ComArithmetic::CArithmeticClassClass(); double answer = arith->Add(2,3); Console::Write("2 + 3 is "); Console::WriteLine(__box(answer));
return 0;}
Wrap the Legacy as a DLL
Win32 project, application type is DLLPull member functions out of the class
Add declspec to each
extern "C" __declspec(dllexport) double Add(double num1, double num2)
{return num1+ num2;
}
Using the DLL from .NET
using namespace System::Runtime::InteropServices;
[DllImport("debug/dllarithmeticglobal.dll")] extern "C" double Add(double num1, double
num2);int _tmain(void){ double answer = Add(4,3); Console::Write("4 + 3 is "); Console::WriteLine(__box(answer)); return 0;}
C++ Is Special
If the Pinvoke defaults are fine with you, leave it out:
extern "C" double Add(double num1, double num2);
int _tmain(void){ double answer = Add(4,3); Console::Write("4 + 3 is "); Console::WriteLine(__box(answer));return 0;}
Finding the DLLAdd the import library to the dependencies
Finding the DLLMake sure the import library is on the linker dependency pathMake sure the DLL is on the executable search path
C++ Is Special
What is happening in this example?No Pinvoke
Linking to a .lib that has unmanaged code
Nothing special about the function declaration
You can even use the .h file from the DLL project with __declspec(dllexport) in it, and the compiler just ignores the declspec
It Just Works!
It Just Works
If you have unmanaged code you want to compile as managed, just compile it
It will compileIt will run
Even if it calls out to unmanaged codeStatically linkedDynamically linkedMFCATLWhatever!
XCopy Porting
Create a new managed applicationCopy the .cpp files and .h files into the project folder
These create non-gc classesProbably call out to other libraries
Use Add, Add Existing ItemNow the code is in the project
Build it!
XCopy PortingBuilds to IL
A Mixed ExeFile-by-file, you can request native code instead of IL
May gain performance
Give up being managed
A Mixed ExeUse the property pages for the file
A Mixed Exe
You can also control managed or unmanaged compilation within a file:Before a function:
#pragma unmanagedint foo();
Use with caution, it can confuse maintainers
Agenda
Setting the stageCOM InteropPInvokeIt Just WorksWhat should you do?
What Should You Do?
PerformanceMaintenance Convenience and Development TimeSecurity and Permissions
Performance
Usually unmanaged code called from unmanaged code is the fastest solution
Sometimes the xcopy port can surprise you
XCopy port may get faster if you make individual files compile to native code
DLL (with or without PInvoke) is slower than these two, but faster than COM
It’s a trace faster without PInvoke
COM Interop has the most overhead
Maintenance
What other applications are using this code now?
How do they call it?
Crazy to maintain a COM component and a class library as separate copies
Even if the class library does execute a bit faster under .NET
Maybe some refactoring is the way to go in that case
Pull functionality into a class libraryCOM component and .NET component both use the class library
Developer Convenience
This is all pretty easy, really
Still, why run around refactoring or wrapping if you don’t need to?
Hard to argue with It Just Works
Avoid maintaining two sets of code, but don’t create wrappers for their own sake
Security
Code Access SecurityGranular Permissions
Access file systemMake SQL connectionCall unmanaged code
Surely each of the ways of reusing legacy C++ code has different security implications?
Skip Verification
By default, all C++ projects demand SkipVerification permission
The IL doesn’t have to pass the Verifier checks
All means allCOM Interop
Pinvoke
XCopy port, 100 % IL
Mixed EXE
No security implications of the reuse choice
Verifiable Code
Starting in Visual Studio .NET 2003, C++ projects can turn off the SkipVerification request, but they must be verifiable
Hardly any C++ code will meet the requirements for verifiable code
No pointer arithmetic
No linking to unmanaged code (IJW), or #pragma unmanaged – no CRT
PInvoke OK
Optimizer off
Bottom Line
If the code you want to reuse is not being used in any other application
XCopy Port
If the code is a COM Component nowCOM Interop
If you notice a performance issue, refactor to a library and a COM component, and use the library from .NET
If the code is a DLL nowUse PInvoke if you need to control marshaling
Otherwise IJW
What About VB and C#?
They can only get to your old code through COM Interop or PInvokeBut you can write a little wrapper class
Managed (__gc) class in Managed C++Wraps each method of the old class and calls it using IJW VB and C# can use language interop on the CLR to call these methodsC++ provides the bridge to the old world
Maximizes performance
Wrapper class
public __gc class ArithmeticWrapper{private: ArithmeticClass* ac;public: ArithmeticWrapper() {ac = new ArithmeticClass();} double Add(double num1, double num2) {return ac->Add(num1,num2);} ~ArithmeticWrapper() {delete ac;}};
Why not make ArithmeticClass __gc?
Can't allocate on stackOld code will break
Can you delete a pointer to a garbage-collected class?
Yes:ArithmeticWrapper* wrapper = new
ArithmeticWrapper();answer = wrapper->Add(5,6);delete wrapper;
Resources and Links
My Code Guru Column www.codeguru.com/columns/Kate/
MSDNmsdn.microsoft.com/visualc/
GotDotNetwww.gotdotnet.com/team/cplusplus/
Community Resources
Community Resourceshttp://www.microsoft.com/communities/default.mspx
Most Valuable Professional (MVP)http://www.mvp.support.microsoft.com/
NewsgroupsConverse online with Microsoft Newsgroups, including Worldwidehttp://www.microsoft.com/communities/newsgroups/default.mspx
User GroupsMeet and learn with your peershttp://www.microsoft.com/communities/usergroups/default.mspx
evaluationsevaluations
© 2002 Microsoft Corporation. All rights reserved.© 2002 Microsoft Corporation. All rights reserved.This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.