views:

521

answers:

3

I'm using Visual Studio 2008 to build a Solution with two Projects: a C# Console App and a C++ DLL. I want the app to call a function from the dll using P/Invoke. Therefore I'm trying to add the dll as a Reference to the C# app. But when I try the Add Reference command, Visual Studio won't let me do it unless I set the /clr property on the dll (under Configuration Properties:General). Now, I thought that P/Invoke could handle plain-old win32 dlls. Indeed, if I build my dll without /clr and just copy it by hand to bin/Debug, then the app runs fine. So why is /clr required to add the dll as a reference? And if VS won't let me add it, is there some (clean) workaround so that my app finds the dll?

I see that someone had a similar issue here (though with a 3rd-party dll): http://stackoverflow.com/questions/1377019/unable-to-add-a-dll-reference-to-vs-2008 The answer he got was to build a wrapper. But this isn't really necessary, since the app can use the dll just fine; it's just the Add Reference step that doesn't work. And besides, won't the wrapper code need a reference to the dll, raising the same problem as before? I'd really like an answer that doesn't involve writing a wrapper at all.

+3  A: 

When using PInvoke on a C++ DLL, it is not necessary to add a reference. References are only needed when you are calling managed code in another DLL. Simply put the C++ DLL in the same directory and add it's name to the DllImport attribute

JaredPar
+3  A: 

Why not just add a post-build step to copy your unmanaged DLL to your project directory? You don't need a "reference" to be able to refer to an unmanaged DLL, and it sounds like the only problem you're experiencing is due to the file not being automatically copied into the search path.

Daniel Pryden
I wrote a pre-build step for the C# app using this command line: copy "$(SolutionDir)Debug\MathDll.dll" "$(TargetDir)". Alas, I wish the "Add Reference" functionality worked, because now I've got to maintain this, and I guess it will be different for release builds.... I don't really see why "Add Reference" shouldn't handle this sort of thing.
Paul A Jungwirth
I just found a slightly cleaner way of doing this. Rather than using a pre/post-build DOS command, I added the dll to the C# project as an "Existing Item." Then under its properties, I set "Copy to Output Directory" to "Copy if newer." (Its "Build Action" is "Content.") This still seems a little hackish to me, but at least it fixes the Debug-vs-Release issue, and it's a little easier to spot.
Paul A Jungwirth
Oops--I realized my second workaround does not resolve the Debug-vs-Release issue, because I referenced the dll from the Debug folder. On the other hand, the first workaround could handle this issue by changing the command to copy "$(SolutionDir)$(Configuration)\MathDll.dll" "$(TargetDir)".
Paul A Jungwirth
A: 

Theoretically you could add the C++-DLL as a linked resource to your C#-DLL. This would make .NET copy your C++-DLL wherever it copies the C#-DLL even into the GAC. Theoretically means that there are some disadvantages:

  • You could instruct the C# compiler (csc.exe) via command line options to add the linked resource but I never found a way to do it via .csproj file or even Visual Studio
  • If the C#-DLL contains WinForms user controls and you want to use it in the designer it wont work because the Winforms-Designer copies the C#-DLL to a temporary location where it loads it but it ignores the linked resource.
  • I don't know if it works if you put your C#-DLL into the GAC (yes the C++-DLL would also go into as a resource, but I don't know if it is found when running your C#-DLL!)

So if none of the above is a no-go for you you can call csc.exe the following:

csc.exe ... /linkresource:cpp.dll

Hope this may help!

rstevens