.NET Forum / .NET Framework / Interop / July 2006
Using /clr in MFC ATL apps
|
|
Thread rating:  |
Juan Dent - 09 Jul 2006 02:07 GMT Hi,
I have a large MFC ATL EXE built with C++ 8, and now I am compiling with /clr to enable C++ interop - i.e. accesing .NET components directly in the same executable as the unmanaged code from MFC/ATL.
When I compile I get a series of warnings and would like to know if they are of concern or not and also what they mean. For instance, I don't quite understand this next warning since CShortcutBarFrame being MFC based it is no surprise it will be natively compiled:
---------------- warning C4793: 'virtual-call thunks are native with /clr' : causes native code generation for function 'CShortcutBarFrame::`vcall'{328}'' ----------------
Next, I have an #import "xx.tlb" which generates the next warning. This tlb is actually generated from an originally all .NET component. My question here is how should I proceed to use this component from C++/CLI with better support and performance? My idea is to use #using "xx.dll". What dangers await me in that road that I could know in advance?
----------------- warning C4279: 'value': identifier in type library 'Exactus.ORM.Gateway.v1.tlb' is a keyword; use the 'rename' qualifier -----------------
Finally, and most importantly, how can I find out which parts of my code are compiled to native and which to MSIL?
 Signature Thanks in advance,
Juan Dent, M.Sc.
"Peter Huang" [MSFT] - 10 Jul 2006 08:42 GMT Hi Juan,
Thanks for your posting! I think you may simple put the error code in the MSDN to get the information. e.g. C4793: Error Message 'reason' : causes native code generation for function 'function' function was compiled to unmanaged, native code, even though the file was compiled /clr. The compiler will not be able to create an MSIL version of the function if the function includes setjmp, inline assembly, or a parameter list that includes a variable number of parameters. This is a level 1 warning when compiling with /clr:pure.
The warning above generally meansthe function have only the unmanaged version and is not visible to .NET.
For your second concern, is how to use the .NET assembly in C++/CLR. My suggestion is to use the #using keyword, because if we use the #import to import the tlb, then the code is just as we do in the legacy unmanaged C++. In which we even did no need the /clr switch. So far,sine your are trying to use /clr and call code with .NET assembly(MSIL) and pure C++, so I think we did not need to #import the tlb file.
If you still have any concern, please feel free to post here.
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Juan Dent - 10 Jul 2006 19:29 GMT Hi,
Thnaks Peter. One thing that was not addressed is how can I know which functions/classes of my /clr compiled EXE will be managed and which will be unmanaged?
 Signature Thanks in advance,
Juan Dent, M.Sc.
> Hi Juan, > [quoted text clipped - 33 lines] > ================================================== > This posting is provided "AS IS" with no warranties, and confers no rights. "Peter Huang" [MSFT] - 11 Jul 2006 03:59 GMT Hi Juan,
Thanks for your quickly reply! I think you may take a look at the good article below.
By throwing the /clr switch, the compiler generates MSIL instead of native machine code. The only code that is generated as native machine code is code that just can't be compiled to MSIL, including functions with inline asm blocks and operations that use CPU-specific intrinsics such as Streaming SIMD Extensions (SSE).
http://msdn.microsoft.com/msdnmag/issues/04/05/VisualC2005/
Remarks The /clr compiler option provides module-level control for compiling functions either as managed or unmanaged. An unmanaged function will be compiled for the native platform, and execution of that portion of the program will be passed to the native platform by the common language runtime.
***Functions are compiled as managed by default when /clr is used.
Use the following guidelines when applying these pragmas: Add the pragma preceding a function but not within a function body. Add the pragma after #include statements (do not use these pragmas before #include statements). The compiler ignores the managed and unmanaged pragmas if /clr is not used in the compilation. When a template function is instantiated, the pragma state at the time of definition for the template determines if it is managed or unmanaged. For more information, see Initialization of Mixed Assemblies. http://msdn2.microsoft.com/en-us/library/0adb9zxe.aspx
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Juan Dent - 12 Jul 2006 01:12 GMT Hi and thanks again Peter. One question, if all functions are by default compiled as managed and you are using MFC/ATL, then there is going to be a lot of changing between managed and unmanaged which I can only expect will produce a VERY poor performance.
Is this correct? Or can I NGEN the EXE and get rid of this? I find when I compiled the large EXE with /clr, it takes a lot longer to do anything than if I compile unmanaged.
Again I was looking in /clr a better solution to integrate my EXE with many .NET components, but I am not sure anymore if this makes sense or I should remain using COM Interop.
What are your thoughts on that?
 Signature Thanks in advance,
Juan Dent, M.Sc.
> Hi Juan, > [quoted text clipped - 39 lines] > ================================================== > This posting is provided "AS IS" with no warranties, and confers no rights. Marcus Heege - 12 Jul 2006 08:10 GMT I would not recommend to compile the whole project with /clr. Leve everything as it is and start with a single empty new file compiled with /clr.
Then, you can define methods in this new file and call them from native code. This means that your normal program flow (apart from startup and shutdown) does not need any managed/unmanaged transitions at all.
Marcus Heege
> Hi and thanks again Peter. > One question, if all functions are by default compiled as managed and you [quoted text clipped - 60 lines] >> This posting is provided "AS IS" with no warranties, and confers no >> rights. Juan Dent - 12 Jul 2006 18:39 GMT Hi and thanks.
But even if I create a new file and compile only this file with /clr, then when I call any function in this file from a function in the other files in the project (which are not compiled with /clr) that would entail a managed to unmanaged overhead, am I wrong?
I mean, how is this better performing than simple old COM Interop? (i.e. placing the managed code in its own assembly and calling functions in it from the unmanaged EXE via CCW).
 Signature Thanks in advance,
Juan Dent, M.Sc.
> I would not recommend to compile the whole project with /clr. Leve > everything as it is and start with a single empty new file compiled with [quoted text clipped - 70 lines] > >> This posting is provided "AS IS" with no warranties, and confers no > >> rights. Marcus Heege - 12 Jul 2006 23:24 GMT Hi Juan
> Hi and thanks. > [quoted text clipped - 4 lines] > to > unmanaged overhead, am I wrong? My point is that you can control very fine-grained how and how often a managed / unmanaged transition takes place. If you have to call a managed function very often, you can factor out some code in your old files into the one compiled with /clr, so that many managed/unmanaged transitions are replaced by one.
> I mean, how is this better performing than simple old COM Interop? (i.e. > placing the managed code in its own assembly and calling functions in it > from > the unmanaged EXE via CCW). It usually performs better, because the thunks created from C++/CLI Interop perform significantly faster. Furthermore, C++/CLI Interop is a two-way interop architecture. You can call from managed code to unmanaged code and from unmanaged code to managed code. At the source code level, the only thing you need for both directions is a method signature. On the other hand, callbacks via COM Interop very likely end up in Runtime Callable Wrappers being used. Runtime Callable Wrappers are a really painful construct. Lifetime management can be very difficult (2 ref counts involved). The worst part about RCWs is that they do not respect the rules of COM Apartment models. Progrmming COM in native C++ can be hard, using COM Interop can add a significant level of complexity to the whole picture.
>> I would not recommend to compile the whole project with /clr. Leve >> everything as it is and start with a single empty new file compiled with [quoted text clipped - 78 lines] >> >> This posting is provided "AS IS" with no warranties, and confers no >> >> rights. "Peter Huang" [MSFT] - 14 Jul 2006 04:21 GMT Hi Juan,
Thanks for Marcus's input and I agree with Juan's suggestion. The VC and CLR teams have done lots of performance analysis. But there isn¡ ¯t a simple answer to this question. Let me say some basic things /clr:safe code will generally perform as well or often better than the equivalent C# code, because the C++ optimizer can make improvements to the IL. If you take advantage of C++-specific constructs and patterns, these gains can be larger. But remember that /clr:safe code can¡¯t use native classes or memory, and so your existing code won¡¯t recompile to safe. /clr:pure code mixes traditional native classes and managed classes in the same image, but with ¡°CLR-style defaults¡±. It¡¯s appdomain friendly, and can benefit from some of the same optimization opportunities as above. Some traditional code can be recompiled to pure, but pure mode is missing some things (__stdcall, for example) that stop some libraries you might want to use (ATL, MFC) from working. This can limit its utility. Calling down to traditional native library functions (printf, strcpy, etc) involves thunking as usual. /clr code mixes traditional native classes and managed classes in the same image, but with ¡°native-style¡± defaults. It is the only one of these models that can link in existing native libraries and other native code not compiled /clr. It is not appdomain friendly (in general), and suffers from thunking costs in some areas. Thunking was improved a bunch in Whidbey, but working with /clr code performance is still quite subtle. /clr code can perform very well, but is likely to require more tuning than the two above. And there is a tension between the CLR and the native models that comes up a lot. Since things like vtable slots are native function pointers by default, you can get a lot of thunking in some scenarios.
Depending on your scenario, you might want to choose one or another of these models. If you have lots of existing code, you probably need /clr right now, but this is the one with the most challenges. Our recommendation in general is for customers to take a large application and recompile specific files /clr rather than throw /clr on the whole application. This path is easier to work with in general. And only the source files that need to work with managed objects or call managed APIs need to be /clr.
Also /CLR is the only option when compiling MFC code. NGEN will not help with thunking issues, it just saves you JIT'ing costs. You may start with this sample: http://www.microsoft.com/downloads/details.aspx?familyid=987021bc-e575-4fe3- baa9-15aa50b0f599&displaylang=en It isolates managed code into an extension DLL.
Best regards,
Peter Huang
Microsoft Online Community Support ================================================== When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|