• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
myvraccount

DLL Import Failure

32 posts in this topic

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?

0

Share this post


Link to post
Share on other sites

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?

0

Share this post


Link to post
Share on other sites

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.

2

Share this post


Link to post
Share on other sites

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?

-1

Share this post


Link to post
Share on other sites

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).

0

Share this post


Link to post
Share on other sites

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.

1

Share this post


Link to post
Share on other sites

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 :-/

0

Share this post


Link to post
Share on other sites

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?

0

Share this post


Link to post
Share on other sites
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.
2

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

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
2

Share this post


Link to post
Share on other sites

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.

-1

Share this post


Link to post
Share on other sites

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.
0

Share this post


Link to post
Share on other sites

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
0

Share this post


Link to post
Share on other sites

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.... :)

0

Share this post


Link to post
Share on other sites

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.

0

Share this post


Link to post
Share on other sites

Add reference is used to add .NET assemblies, such as the Class Library project type. You should not add a reference to a non-.NET dll. Instead, you can add it to your project (Add existing item) and then just modify its properties to "Copy If Newer" (or "Copy Always"). That way your C++ DLL(s) will be copied into your output directory (bin\Debug or bin\Release). You can probably also use the solution properties to setup a dependency if both the C++ project and the C# project is in the same solution, but I've never tried this.

 

You should only copy the .DLL, the .LIB is used if you want to import it from another C or C++ project and the .pdb is just debug information (which might be useful when debugging, but is not required or used when running without debugger).

 

[DllImport("SomeLibrary")] can take the filename with or without .dll. The reason why you may want to do it without the .dll suffix is that it plays better with Mono should you ever want to support Linux or whatever.

 

 

Edit:

When you add a platform and/or a configuration, you basically create a whole copy of the set of settings, which just some single settings changed. If you check your project settings, you can find the target platform under the build tab.

 

I've never really checked what happens when it can find a .DLL for the right platform, but the .DLL does not contain the requested function. Maybe you get a DllNotFoundException in that case as well? How did you export your function in your C++ code? Did you use extern "C"? Did you use a .def file or __declspec( dllexport )?

Edited by DvDmanDT
0

Share this post


Link to post
Share on other sites

Well that's all good to know but the only reason I was copying everything to everywhere was as a precaution, on the off chance that it was not finding it because it was in the wrong place.  And it can't hurt, can it?

 

I just want to make absolutely sure nothing can go wrong, but somehow it still is.

 

What you say about not using references for non-.NET DLLs, assuming it's correct, it would rule out that as a possible cause of the error, and leave me fresh out of ideas!  So now what?

0

Share this post


Link to post
Share on other sites

As I wrote in my edit, how do you export the function? With a .def file or __declspec( dllexport )? Also, you need to use extern "C". Please confirm you have done this..?

 

[Edit]

 

Also, did you tell it to use stdcall in the C++ code? Otherwise you'll need to tell the C# code to import it using Cdecl, unless you are using Linux or Win64. :)

Edited by DvDmanDT
0

Share this post


Link to post
Share on other sites

Well I couldn't find the settings, because there's a project->properties menu item but not project->settings, and I couldn't find any build tab in the properties one.  I had been just using the Configuration Manager, but wondering why the settings weren't available there.  I can right-click on the project in the Solution Explorer and click properties, but that doesn't have a build tab either.  Of course I'm not at my computer now so I can't use VS2012 and am using VS2010 right now instead.  I'm not sure if that makes a difference.  (I'm developing this project on VS2012 express though).

 

I don't think it would have a DllNotFoundException problem if it can't find the function, but then I didn't even think that the problem was that it can't find the function.  Do you think that's what the problem is?  The way I interpreted it, once the error changed to BadImageFormatException, I thought maybe it could find the DLL but it just couldn't read it for some reason.

 

I'm using Win64, it might be nice to have it compatible with Win32 also but it's not essential, and I don't care at all about Linux or Mac etc. for this.

 

How did I export them?  Let's see... I set up the project to make a DLL automatically and then I just added my code to it, but I read through the auto-generated code (this is from memory), and it looked like it was #defining something as "__declspec(ddlexport)" or something extremely similar to that.  I'm pretty sure that was the exact text, and then it used it in the declaration of all functions.  I also thought I saw an extern "C" at some point but I'm not certain of that - I'd have to check, I'm pretty sure though.  I don't think there was any .def file at all.  I think I'd remember that.

 

Also, I tried putting the 3rd party DLL (DLL A) directly into C# instead of using my DLL (DLL B), and that may actually work better in the long run.  I think I got it to even change the exception from DllNotFoundException to BadImageFormatException (which I consider progress).  But if I do it that way I don't know whether it used __declspec(dllexport) or extern "C" or a .def file, but would it even matter?  All they give me is a DLL and a LIB.

 

I've tried my DllImport with .dll extension and with .lib (that didn't work), but I haven't tried it without an extension.  I'm not sure that would make a difference though.

 

I probably need to somehow set the settings for the build mode (32 vs 64 bit) more specifically than I have already.  Either that or I must be overlooking some tiny detail somewhere.

0

Share this post


Link to post
Share on other sites

Just go with 32 bits for everything, unless you really need 64 bits for something (very much memory usage).

 

I created two projects, using VS2010 though. First, I created a C# Console Application project, then I created a Win32 project which I changed in the create project wizard to Dll project and checked the Exports symbols.

 

TheDll.h:

#ifdef THEDLL_EXPORTS
#define THEDLL_API __declspec(dllexport)
#else
#define THEDLL_API __declspec(dllimport)
#endif


extern "C"
THEDLL_API int fnTheDll(void);

TheDll.c:

#include "stdafx.h"
#include "TheDll.h"



// This is an example of an exported function.
extern "C"
THEDLL_API int fnTheDll(void)
{
	return 42;
}

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("It returns {0}", fnTheDll());
        }

        [DllImport("TheDll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int fnTheDll();
    }
}

When I created these projects, the x86 platform was the default for the C# project and Win32 was the default for the C++ DLL project. This showed up as Mixed Platforms. I had to manually copy the TheDll.dll to the Debug folder of my C# project, that is next to my ConsoleProject.exe. Only the .dll and the .exe is needed.

 

If I try to import a function that does not exist, I get an EntryPointNotFoundException. If I change the C# project to build for x64 instead, without changing the C++ DLL to 64 bits, I get a BadImageFormatException. If I don't copy the C++ dll manually to the same folder as the .exe, I get a DllNotFoundException.

 

Edit:

Do note the extern "C" lines. They were added by me, and they are required.

Edited by DvDmanDT
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0