tags:

views:

288

answers:

5

Ok I'm trying to make a C++ DLL that I can then call and reference in a c# App. I've already made a simple dll using the numberous guides out there, however when I try to reference it in the C# app I get the error

Unable to load DLL 'SDES.dll': The specified module could not be found.

The code for the program is as follows (bear with me I'm going to include all the files)

//These are the DLL Files.

#ifndef TestDLL_H
#define TestDLL_H

    extern "C"
    {
        // Returns a + b
        __declspec(dllexport) double Add(double a, double b);

        // Returns a - b
        __declspec(dllexport) double Subtract(double a, double b);

        // Returns a * b
        __declspec(dllexport) double Multiply(double a, double b);

        // Returns a / b
        // Throws DivideByZeroException if b is 0
        __declspec(dllexport) double Divide(double a, double b);
    }

#endif

//.cpp
#include "test.h"

#include <stdexcept>

using namespace std;

    extern double __cdecl Add(double a, double b)
    {
        return a + b;
    }

    extern double __cdecl Subtract(double a, double b)
    {
        return a - b;
    }

    extern double __cdecl Multiply(double a, double b)
    {
        return a * b;
    }

    extern double __cdecl Divide(double a, double b)
    {
        if (b == 0)
        {
            throw new invalid_argument("b cannot be zero!");
        }

        return a / b;
    }

//C# Program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport("SDES.dll")]
        public static extern double Add(double a, double b);
        static void Main(string[] args)
        {
            Add(1, 2); //Error here...
        }
    }
}

Anyone have any idea's what I may be missing in my program? Let me know if I missed some code or if you have any questions.

A: 

it means when it tried to load the dll, it could not find it!

http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx

most likely its not in the same directory as your C# app.

also, good time to mention

http://www.dependencywalker.com/

helps find DLL dependency problems.

Keith Nicholas
A: 

put SDES.dll to the folder where the C# .exe is placed.

Yin Zhu
I did that already. Still have the same error.
Major
@Major. Try to use command line to call your .exe.
Yin Zhu
I ran the c# program's .exe from command line and I got the same error only in text.
Major
A: 

Where is SimulateGameDLL defined? I dont see it in the C/C++ code.

leppie
Thanks for pointing that out Leppie. I was trying a different tutorial and forgot to change it back. I've edited my original post to reflect what it should be, but I still get the same issue.As for having the dll in the same folder as the .exe I've done that and I still get the same issue.
Major
A: 

I just compiled the code, and got no error. Here is my command lines.

> cl /LD test.cpp -o SDES.dll
> csc test.cs
> test.exe
leppie
Did you use the command console, or was this something you added to the properties of the project?
Major
I just used the commandline, like shown above. If you are using VS, you probably have too many options enabled :)
leppie
Probably. When I try the command cl /LD test.cpp -o SDES.dll command in my command prompt I get the error message that it doesn't recognize command cl. Am I missing an extension?
Major
From your start menu, run "visual studio command tool" something like that to get a command line environment with VC .
Yin Zhu
Thanks Yin. I ran those commands and the first one (cl /LD test.cpp -o SDES.dll) and it resulted in the following cl : Command line warning D9002 : ignoring unknown option '-0'cl : Command line warning D9024 : unrecognized source file type 'SDES.dll', object file assumedtest.cppc1xx : fatal error C1083: Cannot open source file: 'test.cpp': No such file or directory
Major
+4  A: 

Download the Dependecy Walker and open your SDES.dll. Check if all the dependent DLLs can be loaded. If you see a missing dependence, put that dll in the target directory, too.

Are you using a 64-bit system? If yes, you should target your C# and C++ to the same architecture (both 32 or both 64 bit).

I just tested your functions and it worked out.

    [DllImport("Native_CPP.dll", CallingConvention=CallingConvention.Cdecl)]
    public static extern double Add(double a, double b); 

    static void Main(string[] args)
    {
        Console.WriteLine(Add(1.0, 3.0));

        Console.ReadLine();
    }

Output:

4

This is what I did with Visual Studio 2010:

  • create a new Solution
  • create a new C# project
  • create a new C++-Dll project (without MFC and other stuff)
  • copy paste your header and cpp-files
  • build the C++-Dll
  • copy the DLL to the Debug/Release (depends on what you are using) directory of your C# project (usually "Solution/CSharpProjectName/bin/Debug/" or "Solution/CSharpProjectName/bin/Release/", respectively)
  • add this P/Invoke signature to the C# file:

    [DllImport("Native_CPP.dll", CallingConvention=CallingConvention.Cdecl)] public static extern double Add(double a, double b);

    Note: I had to pass the parameter CallingConvention.Cdecl, otherwise I got an exception.

  • Run the C#-Project as shown above

P.S: I didn't have to set the architectures. It just worked. (I'm using a x64 machine, with a 64-bit OS.)

Simon
Did it. When I opened the SDES.dll it gave this error: Error: At least one required implicit or forwarded dependency was not found.and the dll that had the question mark icon by it was MSVCR90D.DLL.I included this dll (after a quick search of my computer) into the project solution and I'm still having the same issue.
Major
Ok... by "project solution" you mean the same directory as SDES.dll? However, the dependency walker shouldn't complaint any more.
Simon
Yes. I apologize for not being specific.
Major
What about the architecture? (see edited answer)
Simon
My laptop (the system I'm using to design the program) is 64 bit. I have both to target Any CPU. Do you think switching this to target 64 specifically would change the nature of the issue I'm facing?
Major
I once had this problem, but I got a BadFileFormatException. However, native projects are targeted to 32 bit default (even on 64 bit systems). If you try to load a 32 bit DLL from a 64 bit (="Any CPU" on a 64 bit system) assembly, this will make your applicaiton crash. Try to target both to 32 bit by setting 32 bit, in your c# project.
Simon
I swapped the C# project to target x86 (32 bit) but I'm still getting the same issue.
Major
Hmmm... I'm out of ideas... maybe you could check if there are missing dependencies to MSVCRT90D.DLL ("D" indicates that this is the debug version of MSVCRT90... did you include the release version, too? However, I'm trying to compile and link the project on my machine. I'll tell you if it worked.
Simon
Why are you having a dependency to MSVCRT90DLL? Are you using MFC? If yes, do you really need it?
Simon
MSVCRT90.dll is the C++ Runtime, which is likely used by the 'throw new invalid_argument()' call. Either copy MSCVRT90.dll to alongside the C++ EXE *and* specify it in a **manifest file**, or install the Visual C++ 2008 Redistributable Components which will put MSVCRT90.dll in Windows/System32/.... for anything that needs it.
JBRWilkinson