Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


DLL Import Failure


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
32 replies to this topic

#1 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 07 July 2014 - 07:32 AM

I made a DLL in C++, compiled it just fine, imported the DLL and LIB files into a C# project in VS2012, used the System.Runtime.InteropServices, and attached a [DllImport("DllName.dll")] attribute to the function I wanted to test, making sure the function name and data types match correctly and that it is a static extern function, then tried to call the function.

 

Everything compiled fine without any errors, but then when I run it, as soon as it gets to the line that calls the function, it crashes with a DllNotFoundException.  I'm assuming that it's trying to load in the DLL automatically just before it needs to use it, right?  That's fine, but for some reason it can't find it, even though I placed it in the project and it appears inside VS2012, along with the LIB file.  I also tried changing the extension in the DllImport string to be .lib instead of .dll, and I still get the same error.

 

So does anyone know what I did wrong?



Sponsor:

#2 yellowsputnik   Members   -  Reputation: 968

Like
4Likes
Like

Posted 07 July 2014 - 08:01 AM

Have you tried putting the dll in the same directory as the exe file that's using it?



#3 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 07 July 2014 - 09:57 AM

Do you mean inside the debug folder?  Or do you mean somewhere else?  This is a .NET project remember (I guess there's an exe, but it's not machine language, just byte code), but with a DLL that was made in C++.

 

I think I only tried putting it in the main project folder, and also the sub-folder inside of it that has the same name (it nests an extra project folder, like there's one for the solution and one for the project).

 

Anyway, it's imported into the project so it should be able to find it, I would think.  Also, is it supposed to say "DllName.dll" in the DllImport attribute, or should it be a .lib instead?

 

Are there any other files I need to put into the project besides the .dll and .lib?



#4 Karsten_   Members   -  Reputation: 1780

Like
3Likes
Like

Posted 07 July 2014 - 10:38 AM

The .dll should be the correct one. .lib files are not used like that (On Linux you would use .so rather than .lib too).

However in Unity C# you do not seem to need to pass in the .dll suffix (may be optional). Perhaps try:

 

[DllImport("DllName")]

 

Have a look here: http://docs.unity3d.com/Manual/Plugins.html

 

Btw, this is a Unity Pro only feature so that could be your issue.

 

Perhaps also make sure you are not trying to compile for the Web Player. That has extra restrictions preventing native code for security sandboxing reasons.

 

Can you make sure your .dll does not require any other dlls? Usually if they require more .dlls then it could fail to load. There are tools on Windows that should help you find out (perhaps try depends (http://www.dependencywalker.com)).

 

Perhaps also make sure that you have built a native .dll. It is quite likely that you already know this but if you generated a .NET dll using Microsoft C++/clr:safe or pure, it will not work when loaded in like this.

 

Finally, I once noticed that when I made a Unity plugin with wxWidgets, it actually had to have the wxWidgets dll in the same directory as Unity.exe. Perhaps try this if none of the other suggestions work.


Edited by Karsten_, 07 July 2014 - 10:43 AM.

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.


#5 yellowsputnik   Members   -  Reputation: 968

Like
2Likes
Like

Posted 07 July 2014 - 02:41 PM

Do you mean inside the debug folder?  Or do you mean somewhere else?  This is a .NET project remember (I guess there's an exe, but it's not machine language, just byte code), but with a DLL that was made in C++.

 

I think I only tried putting it in the main project folder, and also the sub-folder inside of it that has the same name (it nests an extra project folder, like there's one for the solution and one for the project).

 

Try to find the exe and put the dll in the same folder.

 

You can also try putting it in the Windows folder, but I'm not sure about that at the moment. It could be syswow64 inside the Windows folder as well (for a 32bit program on 64bit Windows). This is just for testing though, you shouldn't put dlls there for a release version.



#6 myvraccount   Members   -  Reputation: 150

Like
-1Likes
Like

Posted 07 July 2014 - 02:44 PM

First of all, who ever said anything about Unity?  I never once mentioned it.  I'm using Visual Studio 2012 C#, that's it, no Unity.  I'm not using any wxWidgets, and I don't even know what the "Web Player" is.

 

I made the DLL in C++.NET so I guess it's possible that it is a .NET DLL.  I guess I assumed it was a regular one.

-  How could I be sure?

-  And if it's not, how can I recompile it into a regular one?

-  But if it's a .NET one, might that still work anyway, even if I have to import it differently?

-  And for that matter, would it still even have a .LIB file with it, or does that prove that it's a regular DLL?

 

Now that you mention it though, it does require another DLL.  I don't remember whether I included that into the project as well.  Should I just include both of them and put both of them into the debug folder where the EXE is?



#7 Karsten_   Members   -  Reputation: 1780

Like
3Likes
Like

Posted 08 July 2014 - 04:40 AM

First of all, who ever said anything about Unity?  I never once mentioned it.

Heh, yeah, my bad. I kinda made the assumption that guys here using C# are probably using Unity. Much of my suggestions are C# issues in general than Unity so at least that cuts out licensing restrictions.

 

Now that you mention it though, it does require another DLL.  I don't remember whether I included that into the project as well.  Should I just include both of them and put both of them into the debug folder where the EXE is?

Normally just include them in the same folder as the .NET executable. However try compiling them in release mode. I think debug versions of the binaries could potentially cause issues.

 

If your .dll does come with a .lib file, then yeah it is likely to be a traditional native dll. So no problems here.


Edited by Karsten_, 08 July 2014 - 04:40 AM.

Mutiny - Open-source C++ Unity re-implementation.
Defile of Eden 2 - FreeBSD and OpenBSD binaries of our latest game.


#8 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 08 July 2014 - 08:24 AM

OK so just to be clear, I should compile the DLLs made in C++ in release mode instead of debug mode (good idea btw), but then I can still run my .NET application in debug mode while using the release mode DLL, right?  And in that case, to put them in the same folder as the .NET EXE would probably still be the debug folder though, right?

 

(Also, thanks for all your help).



#9 Dave Hunt   Crossbones+   -  Reputation: 3510

Like
1Likes
Like

Posted 08 July 2014 - 09:32 AM

If it's a true .NET DLL, then you shouldn't need to do any DllImport at all. Just add a reference to the DLL (right-click References in Solution explorer and click Add Reference...). When the project builds, it will automatically copy the DLL to the correct output directory.

 

If it's not a true .NET DLL, then you will need the DllImport and you need to manually place the DLL in the same directory as your app's .exe directory. That directory will be under either the Debug or Release directory under your project, depending on whether you're doing a Debug or Release build.

 

If the DLL depends on other DLLs that aren't in your environment path, then you'll need to either add references to them (for .NET DLLs) or copy them to your .exe directory as well.



#10 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 08 July 2014 - 02:24 PM

Well thanks.  I'll try all this out when I get some free time (this weekend), and I'll tell you if I still have any problems.  But if anyone has any more suggestions, feel free to post them, 'cause you never know if I might need them :-/



#11 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 15 July 2014 - 07:32 AM

Well here's a summary of what I've tried and what it's doing now:

 

To review, I have a third party DLL compiled to machine language (DLL A), and I used that inside a C++ project to make my own DLL which builds onto it (DLL B), and compiled it and put it into a C# project.  I import it using the interop service and my syntax is good and everything compiles correctly, but when I try to call a function in it, I was getting a DllNotFoundException.

 

That's where I was at my previous post.  Since then:

-  I've put DLL B into each of the possible folders where it could be accessed (the solution, project, debug and release folders) to make sure it's finding it.

-  I also recompiled DLL B in release mode instead of debug, and re-copied it into those folders.

-  I also included DLL A into those folders and imported it into the project.

 

At least one of those things must have partially fixed it, because I no longer get a DllNotFoundException when I call the function; instead I get BadImageFormatException, and it says "An attempt was made to load a program with an incorrect format." and it says "HRESULT: 0x8007000B".

 

As an alternative, I also tried to just include DLL A instead of DLL B, with the intention of recreating DLL B within C# by using DLL A directly.  I include and reference DLL A and its functions the same way I was doing with DLL B, but I just get a DllNotFoundException.

 

I don't really care which way works, because DLL B is simple and I can recreate it (it might even be cleaner that way) but whatever way works is fine with me.

 

Does anyone know what I'm doing wrong?



#12 SmkViper   Members   -  Reputation: 3196

Like
2Likes
Like

Posted 16 July 2014 - 09:04 AM

How are you compiling you C# code? The most likely problem I can think of is your C# code is compiled with "Any CPU" (the default in Visual Studio) which can mean that you're running 64-bit C# code on a 64-bit OS, but your C++ DLLs are 32-bit. So the OS goes looking for a 64-bit DLL and can't find one, so it errors.

When you interop between .NET and native code, you need to make sure that you're using the same bitness, so try forcing your build platform for C# to x86 (32-bit) or x64 (64-bit) depending on how you compiled your C++ DLL.

#13 yellowsputnik   Members   -  Reputation: 968

Like
1Likes
Like

Posted 16 July 2014 - 09:33 AM

I second what SmkViper said, this sounds like you're trying to use a 32bit dll from a 64bit program or vice versa.

 

It seems to be corroborated by this StackOverflow post:

http://stackoverflow.com/questions/2023766/an-attempt-was-made-to-load-a-program-with-an-incorrect-format-even-when-the-p



#14 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 16 July 2014 - 01:49 PM

That's a great idea; I'll try it!

 

But there would still be a few problems:

 

A)  That wouldn't explain why when I import DLL A (explained above) directly instead of DLL B, I'm getting a DllNotFoundException even though I'm now doing it the same way as when I import DLL B.  Ultimately if it works the other way this is a moot point, but I'm still curious about it anyway, and some day I may need to do this.

 

B)  From what SmkViper says, it sounds like I can't make a 64 bit program recognize a 32 bit DLL.  That can't be right though, because what if I need a program to be 64 bit, but use a 32 bit DLL?  Or what if I need a program to use 2 different DLLs and one is 64 bit and the other is 32 bit and I can't recompile them because I don't have the source?  There would have to be a way to do this.



#15 Nypyren   Crossbones+   -  Reputation: 7176

Like
2Likes
Like

Posted 16 July 2014 - 02:03 PM

B)  From what SmkViper says, it sounds like I can't make a 64 bit program recognize a 32 bit DLL.  That can't be right though, because what if I need a program to be 64 bit, but use a 32 bit DLL?  Or what if I need a program to use 2 different DLLs and one is 64 bit and the other is 32 bit and I can't recompile them because I don't have the source?  There would have to be a way to do this.


64-bit processes can't load 32-bit DLLs, and vice versa. All EXEs/DLLs loaded into the process must match.

The exception is that .Net's "Any CPU" DLLs can be loaded into 64-bit or 32-bit processes because the JIT can generate the appropriate code either way.

.Net's "Any CPU" EXEs, on the other hand, will start a 64-bit process if your OS is 64-bit, or a 32-bit process if the OS is 32-bit, but any DLLs loaded thereafter have to match the bit size the EXE picked.


If you don't have proper versions of all DLLs and don't have the source code, you have to go with the bitness that you have available (32-bit, in most cases). When making a .Net EXE which loads 32-bit DLLs, you have to make sure to change the .Net projects to target x86 instead of "Any CPU".

Edited by Nypyren, 16 July 2014 - 02:05 PM.


#16 myvraccount   Members   -  Reputation: 150

Like
-1Likes
Like

Posted 17 July 2014 - 08:25 AM

Right, but what if I wanted to use 2 DLLs in the same project, and one is 32 bit and the other is 64 bit, is it impossible to make any program that will use both DLLs?  That seems absurd.



#17 Dave Hunt   Crossbones+   -  Reputation: 3510

Like
0Likes
Like

Posted 17 July 2014 - 08:49 AM

Right, but what if I wanted to use 2 DLLs in the same project, and one is 32 bit and the other is 64 bit, is it impossible to make any program that will use both DLLs?  That seems absurd.

 


64-bit processes can't load 32-bit DLLs, and vice versa.


#18 SmkViper   Members   -  Reputation: 3196

Like
0Likes
Like

Posted 17 July 2014 - 08:50 AM

Right, but what if I wanted to use 2 DLLs in the same project, and one is 32 bit and the other is 64 bit, is it impossible to make any program that will use both DLLs?  That seems absurd.


That's correct. You cannot mix 32-bit and 64-bit DLLs in the same program. You can, however, make two programs. The 32-bit program that uses 32-bit DLLs, and a 64-bit program that uses 64-bit DLLs.

I suppose if you're really persistent you could have your X-bit program load X-bit DLLs, and then use inter-process communication to load and talk to a separate Y-bit process that loads Y-bit DLLs. But you're going to basically be throwing performance out the window at that point.

Edited by SmkViper, 17 July 2014 - 08:51 AM.


#19 RobTheBloke   Crossbones+   -  Reputation: 2349

Like
0Likes
Like

Posted 18 July 2014 - 10:15 AM

Right, but what if I wanted to use 2 DLLs in the same project, and one is 32 bit and the other is 64 bit, is it impossible to make any program that will use both DLLs?  That seems absurd.

 

If you need to mix 32bit + 64bit DLL's, then the only option you have is to use an IPC approach (pipes, named pipes, network socket), and use that to connect two applications together. It's neither nice, nor fun. Ditch the 32bit DLL and move on.... :)



#20 myvraccount   Members   -  Reputation: 150

Like
0Likes
Like

Posted 21 July 2014 - 09:42 AM

Alright, I'm SO CLOSE, but I still have a bit of a problem.

 

So I tried the 32/64 bit thing.  I tried changing it in the Build->Configuration Manager menu, both the Platform and the Active solution platform.  It's odd, because in both cases, the only option initially was Any CPU, but I clicked New and there were options for Win32 and 64 bit, but no way to customize their options (other than copying settings from an existing one, which I also tried).  Why aren't there any options to set, anyway?  Is it sufficient to just pick which one you want and leave it at that?  And if so, why do I have to choose them from "New"; shouldn't they just already be on the list?

 

Anyway, the third party DLL I'm using (DLL A) is apparently available in 32 or 64 bit, so I tried both.  I tried them directly in the project, setting the platform settings to match, and I alternatively tried putting DLL A into a C++ project to make my DLL (DLL B), and then import that one.  In that case, I had to make everything 32 bit, because it seemed like my C++ project was stuck that way, but I was able to compile and import that into my other project.

 

In all cases, when I called the functions, I got DllNotFoundException or BadImageFormatException, and usually I could manipulate the first one into the second one by changing some settings (it seems to me that the second exception is not as bad, and closer to the goal).  But no matter what I did, I couldn't get rid of the exceptions completely so I could actually run the functions.

 

Also, when I "import" DLLs into my project, what I've been doing is placing the DLL, LIB, PDB and another file (I don't remember the extension off hand) into every folder within my project JUST IN CASE it's looking for it somewhere I wouldn't expect, then inside the project I "Add existing item" and pull them all in that way.

 

I thought that would be sufficient, but then I noticed that there is an "Add reference" on the menu, which then allows me to choose DLLs from a list of ones that are apparently already associated with the project in some way or another (like mine because I included it in the project).  On this list, I checked the box to import it and clicked OK, but I got an error.  Unfortunately I don't have the text with me, because I wrote down so many notes about errors I accidentally brought the wrong one, but I think it essentially said that it couldn't import it for some reason or wasn't compatible or something.  Sorry if that's vague.  I'll try to be more specific tomorrow when I bring the note.

 

So if anyone happens to know what I'm doing wrong, I would appreciate if you tell me please!  Thank you.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS