LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

CVI call to Managed C++ DLL causes 'General Protection' fault

Hi,

I'm calling a C++ DLL from LabWindows/CVI 6.0 which contains both managed and unmanaged C++ code.  When CVI tries to run, it crashes with a "General Protection" fault. 

As a workaround, I've created a totally unmanaged wrapper DLL that calls my managed DLL using LoadLibrary().  This workaround does NOT cause CVI to crash.  But it's unacceptable, because I have hundreds of functions to wrap.

Why is CVI crashing when it tries to call the unmanaged interface of a C++ DLL that has managed code? 

Thanks,

Hans
0 Kudos
Message 1 of 11
(6,338 Views)
Hi Hans,

if you are trying to call a .NET assembly from LabWindows/CVI (which I think you are because you mentioned creating a managed C++ DLL which is an assembly), you need to be using our .NET Library and the .NET Controller Wizard. Check out this post that I responded to.

If you use the .NET libraries available in CVI, you don't need to create any wrapper DLLs that would call the managed code.

Hope this helps!

Best Regards,
Jonathan N.
National Instruments
0 Kudos
Message 2 of 11
(6,335 Views)

Have you tried loading and calling your mixed-mode DLL from a plain C program in Visual Studio? I would suggest that you try this. You may get get the same crashes as in CVI. Various rules need to be followed when loading and calling mixed-mode DLLs; specifically, the Microsoft C/C++ runtime library might need to be initialized by calling certain functions or creating certain objects. You can find more information on this from msdn. For example:

http://msdn2.microsoft.com/en-us/library/aa290048(VS.71).aspx

0 Kudos
Message 3 of 11
(6,332 Views)
Hi Johnathan,

The DLL I'm calling isn't a pure .NET Assembly - it's a Mixed Mode DLL, i.e. it contains both Managed .NET MSIL code and Unmanaged C/C++ code.  I'm calling one of the unmanaged functions exported by the DLL.  And in fact - the function I'm calling doesn't even make any calls into the managed portion of the DLL.

I'm not interested in calling .NET Assemblies from CVI because the requirements for this Mixed Mode DLL are that it has a C compatible interface. 

Is there a known issue with CVI 6.0 linking to Mixed Mode DLLs?

Best,

Hans

0 Kudos
Message 4 of 11
(6,322 Views)
Hi Mohan,

I have tested this with a C console app created in VC6.0 and it works fine.  My C program has no problem linking to and calling the unmanaged interface of my Mixed Mode DLL.

Also, the rules that Microsoft refers to have to do mostly with DllMain and I don't appear to be violating any of those rules.

My CVI 6.0 app crashes on initialization - it doesn't even get to the point in the code where the call is made.  And as I mentioned in the above reply, the function I'm calling doesn't even call into the managed portion of my Mixed Mode DLL!

Why doesn't CVI 6.0 support linking to Mixed Mode DLLs?

Hans

0 Kudos
Message 5 of 11
(6,322 Views)
How are you linking to the mixed-mode DLL? Are you calling LoadLibrary and GetProcAddress, or are you linking statically? I would recommend trying LoadLibrary/GetProcAddress as it avoids import library incompatibilites. CVI 6.0 is somewhat old - released in Aug 2001, much before VC2003. I vaguely remember that some aspects of VC library stuff was changed in VS 2003 - I could be mistaken.
 
When you get the GPF, you will get the address where it crashed. If your program is attached to a debugger, you could get the addresses of the loaded modules and check which module crashed. If the crash is in your DLL, then probably it is something to do with the initialization (DllMain or initializing the VC C runtime); if it is crashing in your CVI exe module, then it is probably because there is some incompatibility between the CVI linker and the VC import library.
 
Also, if you call your DLL using LoadLibrary, your DllMain will get called (hopefully), and you can put a breakpoint there and see what is going on. If DllMain is not even getting called, then there are other issues. I have successfully called mixed-mode DLLs built in VC 2003 and VC 2005 from CVI 7.x and higher using dynamic linking.
0 Kudos
Message 6 of 11
(6,289 Views)
The CVI app is linking directly to my Mixed Mode DLL.  I haven't tried using LoadLibrary in my CVI app only because that's functionally the same as my current workaround (wrapping my Mixed Mode DLL with a pure unmanaged DLL that uses LoadLibrary to call into the Mixed Mode DLL). 

BTW - the source of the crash is occuring in ntdll.dll, which is shared by both the parent CVI.exe process and my CviApp.exe process and it occurrs WAY before I can attatch any debuggers.  So I'm convinced it's a DLL initialization issue.

As far as VC Library changes / incompatibilites are concerned, you may very well be correct.  However, I have a test case in which a VC6.0 C app makes the same calls into my Mixed Mode DLL and it doesn't crash. It's not using LoadLibrary either. VC6 is like circa 1998 - way before Microsoft could have started messing with lib formats.

If a VC 6 app works, a CVI 6.0 app should too, right?!

0 Kudos
Message 7 of 11
(6,273 Views)
I have only used mixed-mode DLLs from CVI 8.x, not CVI 7.x as I incorrectly stated in the previous post. I have only done this with dynamic linking and have not tried static linking. Having said that, do take a look at:

http://msdn2.microsoft.com/en-us/library/ms384212(VS.71).aspx

It looks like you need to make sure Microsoft's C runtime library is properly initialized before calling any thing else in your DLL. I am not sure if you have already done this. Alternative 1 is probably what applies to your use case, and if so, you would need to export two more functions to intialize and terminate the MS C runtime library properly, and call these as indicated by that MSDN page. In my case, I also used these special exports, though I cannot remember if it crashed without them. I think with the above, you should be fine whether you load and call the DLL statically or dynamically.

The reason why calling your DLL from VC-based applications works just fine is possibly because the MS C runtime library is getting initialized by that application's C runtime linkage, whereas this would not be possible from CVI. This is also explains why it did not crash when you created an intermediate C DLL - the intermediate DLL was initializing the MS C runtime library before the mixed-mode DLL needed to call into it.
0 Kudos
Message 8 of 11
(6,242 Views)
Hi Mohan,

Thanks for the link.  Unfortunately we've already tried all the suggestions made in that article to no avail.  I think that article was dealing with how to handle more complex Dll initialization issues.  Either way - linking with /NOENTRY, etc. doesn't appear to remedy the problem.  I suspect the CVI runtime is mismanaging the load of the C runtime in some way?

Anyway - we've got a totally bare bones test case that I've emailed to NI that clearly fails to initialize when statically linking with CVI 6.0 and/or 8.0.  And again - it is clear that the initialization failure in CVI occurs way before we can attatch a debugger, much less perform any dynamic calling of pre/post crt initialization code.  AND, it only occurs when statically linking.  If I use LoadLibrary and GetProcAddress in my CVI app all is well. 

If you find yourself stuck in an airport with your laptop and some time on your hands, try it out yourself - you'll see!  I'm including our test case if you want to try it out.

Cheers,

Hans

0 Kudos
Message 9 of 11
(6,178 Views)
I looked at the attached files. Yes, linking via import library just does not work. I also dug up my mixed-mode C++ project and if I try to call that from CVI by linking to the import library, I get the same crash. So, this crash is not particular to your project but seems to be a general incompatibility in using mixed-mode C++ import libraries in CVI. Also, I looked at the process when the crash occurs - it seems like Windows is able to map the mixed-mode DLL into the process but crashes in ntdll before calling into the DLL! Not sure why this happens but seems to be because of some inconsistency in how CVI links the mixed-mode C++ import library.
 
Sorry if the above is not of much consolation. I have one suggestion that might make your life easier: You can easily generate the LoadLibrary/GetProcAddress wrapper layer in CVI by opening the mixed-mode DLL header file in CVI, and doing, "Options >> Generate DLL Import Source". This will generate a C source file with the necessary code to call your mixed-mode DLL dynamically. You need to replace the two "???" error codes with some numbers and add the file to your project replacing your mixed-mode DLL import library. This worked fine with your project on my machine.
Message 10 of 11
(6,162 Views)