16

I've a little question to ask you.

I have one C++ source and one header files. The C++ file uses windows.h library, makes operations using serial port(basic operations: read(), write() etc.).

What I want to do is, creating a library using these files, and use that library in my C#.Net solution.

What type of library I need to create? How can I do it? After creating library, How can I import it to C# solution?

My best regards.

Code Parts I'm using:

// MathFuncsDll.h

namespace MathFuncs
{
    class MyMathFuncs
    {
    public:
        // Returns a + b
        static __declspec(dllexport) double Add(double a, double b);

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

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

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

// MathFuncsDll.cpp
// compile with: /EHsc /LD

#include "MathFuncsDll.h"

#include <stdexcept>

using namespace std;

namespace MathFuncs
{
    double MyMathFuncs::Add(double a, double b)
    {
        return a + b;
    }

    double MyMathFuncs::Subtract(double a, double b)
    {
        return a - b;
    }

    double MyMathFuncs::Multiply(double a, double b)
    {
        return a * b;
    }

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

        return a / b;
    }
}

C# import part:

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

static void Main(string[] args)
{
    string a = Add(1.0, 3.0));
}
unnamed
  • 840
  • 9
  • 26
  • 38

4 Answers4

14

After several comments, here a try:

C++ Code (DLL), eg. math.cpp, compiled to HighSpeedMath.dll:

extern "C"
{
    __declspec(dllexport) int __stdcall math_add(int a, int b)
    {
        return a + b;
    }
}

C# Code, eg. Program.cs:

namespace HighSpeedMathTest
{
    using System.Runtime.InteropServices;

    class Program
    {
        [DllImport("HighSpeedMath.dll", EntryPoint="math_add", CallingConvention=CallingConvention.StdCall)]
        static extern int Add(int a, int b);

        static void Main(string[] args)
        {
            int result = Add(27, 28);
        }
    }
}

Of course, if the entry point matches already you don't have to specify it. The same with the calling convention.

As mentioned in the comments, the DLL has to provide a C-interface. That means, extern "C", no exceptions, no references etc.

Edit:

If you have a header and a source file for your DLL, it could look like this:

math.hpp

#ifndef MATH_HPP
#define MATH_HPP

extern "C"
{
    __declspec(dllexport) int __stdcall math_add(int a, int b);
}

#endif

math.cpp

#include "math.hpp"

int __stdcall math_add(int a, int b)
{
    return a + b;
}
Simon
  • 1,496
  • 8
  • 11
  • Simon, that made the trick. Thank you. but, What if I have a header file for my source file? Do I have to add extern "C" again? if so how? Thank you again... – unnamed Dec 03 '11 at 14:54
6

You need to compile your C++ code into a dynamic link library and do the following in C#:

  class MyClass
  {
  [DllImport("MyDLL.dll")]
  public static extern void MyFunctionFromDll();

        static void Main()
        {
              MyFunctionFromDll();
        }
  }
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I don't get it, could you pls expand what you mean? – unnamed Dec 03 '11 at 09:15
  • Which part? You need to create a dll (in this example, the dll is called MyDLL.dll, and declare the function from the dll as showed here (in the example, MyFunctionFromDll()) – Luchian Grigore Dec 03 '11 at 09:17
  • Sir, I can't add the library I've created. Visual Studio pops out an error. In additon, I can't use DllImport keyword in my C# solution. – unnamed Dec 03 '11 at 09:28
  • Guess I need to add using System.Runtime.InteropServices; So, I don't have to add a library as a referance to use in C# solution? Just using DllImport? – unnamed Dec 03 '11 at 09:36
  • When I run the project, exception occurs. is says Unable to load DLL. – unnamed Dec 03 '11 at 09:48
  • This is typically the case if the DLL is at the wrong location, try to put next beside the exe, in the project dir, etc. – Simon Dec 03 '11 at 09:53
  • @Simon, I put the dll file in the solution "Solution/CSharpProjectName/bin/Debug". Now it says Unable to find an entry point 'functionname' in DLL 'dllname' – unnamed Dec 03 '11 at 10:16
  • @Un_NatMenDim is the function exported? You need to add _declspec(dllexport) in the function declaration. – Luchian Grigore Dec 03 '11 at 10:17
  • Here it is: static __declspec(dllexport) double Add(double a, double b); – unnamed Dec 03 '11 at 10:20
  • @Luchian Grigore, sir it doesn't have to be. I just use msdn example. – unnamed Dec 03 '11 at 10:26
  • @Un_NatMenDim why are you calling me sir? – Luchian Grigore Dec 03 '11 at 10:34
  • Are you sure your declaration in the C# class matches the one in the dll: public static extern double Add(double a, double b); – Luchian Grigore Dec 03 '11 at 10:35
  • @Luchian Grigore, just trying to be polite :) – unnamed Dec 03 '11 at 10:35
  • @Luchian Grigore, in C# call: public static extern double Add(double a, double b); The same ,yes. – unnamed Dec 03 '11 at 10:37
  • The symbols has to be exported with __declspec(dllexport) AND marked as extern "C" OR by using a *.def File (which is doing both in one). You could use the Dependency Walker to see the exported functions of the DLL. – Simon Dec 03 '11 at 11:19
  • @Simon, I used extern "C", but errors occurs. "IntelliSense: linkage specification is not allowed". – unnamed Dec 03 '11 at 12:35
  • I can't help you without code - probably you have /clr specified in your native DLL? – Simon Dec 03 '11 at 13:51
  • Ok.. you have to export free functions, using extern "C". Class functions are not working - P/Invoke requires a C- interface (that means also, you cannot throw an exception). – Simon Dec 03 '11 at 14:27
  • @Simon, I've tried to add extern "C"{ }, but errors occurs. "IntelliSense: linkage specification is not allowed" – unnamed Dec 03 '11 at 14:39
  • Perhaps time to take this to a chat room? – Kev Dec 03 '11 at 15:11
1

In addition to Lichian's offer to compile to a regular DLL and use p/invoke which is probably the simplest way You can also create your C++ as a COM component (probably something you don't want to do) and the 3rd option you have is to add a thin layer of C++/CLI e.g.

using namespace System;

namespace youcomany{ namespace CPPWrapper
{
    Wrapper::Function(String^ parameter)
    {
        //call the rest of you C++ from here
        }
}}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Arnon Rotem-Gal-Oz
  • 25,469
  • 3
  • 45
  • 68
1

You may use C# DllImport and Dllexport for DLL Interop walkthrough as a starting point. And here is the Platform Invoke Tutorial

Hope this helps.

Eugene Cheverda
  • 8,760
  • 2
  • 33
  • 18