none
How to create a C++ DLL that can be called from a C# program RRS feed

  • Question

  • Can someone kindly please tell me the DETAILED steps on how to create a SAMPLE/DUMMY ansi C++ DLL file that can be called from a C# program? (if possible please provide me the codes for a SAMPLE/DUMMY C++ DLL) My DLL has to be in ANSI C++. I tried creating a C++ DLL by....

    -opens up visual studio 2010
    -choose new project
    -choose C++ win32 console application
    -check on DLL and empty project
    and create .h and .cpp files and starts typing codes in...

    HOWEVER, I failed to add the DLL into my C# reference and failed to import over by using PInvoke.

    this is how my codes look like in the C#:

    namespace CreateMaze
    {
        public partial class Form1 : Form
        {
            public static extern double Add(double a, double b);

    ...................

    .....................

    this is how my codes look like in the C# button:

    private void btnRun_Click(object sender, EventArgs e)
    {
         label7.Text = Convert.ToString(Add(5.0, 6.0));
    }

    For my DLL, I created the MathFuncsDll.dll (I found the codes in MSDN forum, search for Dynamic Library)


    • Edited by Melsoon Friday, March 16, 2012 1:37 AM
    • Moved by Leo Liu - MSFT Monday, March 19, 2012 5:46 AM Moved for better support. (From:Visual C# General)
    Friday, March 16, 2012 1:16 AM

Answers

  • Hello,

    The rules for making a DLL for C# are generally the same also for making a DLL that applies to VB6, so there are a lot of resources.

    # Avoid name mangling in the DLL. That is, put "extern c" in the correct places in the header, or make a pure C DLL.

    # ensure the calling convention is correct. Usually you want the "stdcall" calling convention for x86. For x64 it's always the "fastcall" calling convention. This was the main reason for when learning that most DLL's can't be imported

    # Some datatypes are difficult to pass and return back. In particular I had problems passing float/double in the signature of my C classes. References/Pointers worked better. I don't know why.

    When using your DLLs within C#, check the path that everything is correct. Write the correct P/Invoke method. There's a wonderful website "pinvoke.net" with lots of examples to compare with the system DLLs. Use Dependency Walker to check your DLL, that all dependencies are fullfilled. You can use this tool to ensure that no name mangling occurs (http://www.dependencywalker.com/).

    Monday, March 19, 2012 5:11 PM

  • http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/2c2718c7-19e4-4879-974d-bd9f207e8a32


    The only thing you are missing is the invoke is the attribute tag:

    [Dllimport("the dll path")]

    public static extern double Add(double a, double b);


    Another big thing: For some reason (unknown to me at least) you cannot export static c++ class functions. No idea why. Make them standard C, and you'll be fine. So change your header file to:

    namespace MathFuncs
    {
    
            // Returns a + b
            __declspec(dllexport) extern "C" double Add(double a, double b);
    
            // Returns a - b
            __declspec(dllexport) extern "C" double Subtract(double a, double b);
    
            // Returns a * b
            __declspec(dllexport) extern "C" double Multiply(double a, double b);
    
            // Returns a / b
            // Throws DivideByZeroException if b is 0
            __declspec(dllexport) extern "C" double Divide(double a, double b);
    }

    If you need to wrap C++ classes, that's another monster entirely, but still very doable with C++/CLI. (though that looks out of scope for your question.)

    • Proposed as answer by Idea Hat Monday, March 19, 2012 6:04 PM
    • Marked as answer by Lie YouModerator Thursday, March 22, 2012 3:08 AM
    Monday, March 19, 2012 6:03 PM

All replies

  • My DLL codes are....

    // 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;
        }
    }

    Friday, March 16, 2012 1:18 AM
  • To be able to call those functions with p/invoke, they must not be part of a class.

    Friday, March 16, 2012 8:35 AM
  • Hello,

    The rules for making a DLL for C# are generally the same also for making a DLL that applies to VB6, so there are a lot of resources.

    # Avoid name mangling in the DLL. That is, put "extern c" in the correct places in the header, or make a pure C DLL.

    # ensure the calling convention is correct. Usually you want the "stdcall" calling convention for x86. For x64 it's always the "fastcall" calling convention. This was the main reason for when learning that most DLL's can't be imported

    # Some datatypes are difficult to pass and return back. In particular I had problems passing float/double in the signature of my C classes. References/Pointers worked better. I don't know why.

    When using your DLLs within C#, check the path that everything is correct. Write the correct P/Invoke method. There's a wonderful website "pinvoke.net" with lots of examples to compare with the system DLLs. Use Dependency Walker to check your DLL, that all dependencies are fullfilled. You can use this tool to ensure that no name mangling occurs (http://www.dependencywalker.com/).

    Monday, March 19, 2012 5:11 PM

  • http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/2c2718c7-19e4-4879-974d-bd9f207e8a32


    The only thing you are missing is the invoke is the attribute tag:

    [Dllimport("the dll path")]

    public static extern double Add(double a, double b);


    Another big thing: For some reason (unknown to me at least) you cannot export static c++ class functions. No idea why. Make them standard C, and you'll be fine. So change your header file to:

    namespace MathFuncs
    {
    
            // Returns a + b
            __declspec(dllexport) extern "C" double Add(double a, double b);
    
            // Returns a - b
            __declspec(dllexport) extern "C" double Subtract(double a, double b);
    
            // Returns a * b
            __declspec(dllexport) extern "C" double Multiply(double a, double b);
    
            // Returns a / b
            // Throws DivideByZeroException if b is 0
            __declspec(dllexport) extern "C" double Divide(double a, double b);
    }

    If you need to wrap C++ classes, that's another monster entirely, but still very doable with C++/CLI. (though that looks out of scope for your question.)

    • Proposed as answer by Idea Hat Monday, March 19, 2012 6:04 PM
    • Marked as answer by Lie YouModerator Thursday, March 22, 2012 3:08 AM
    Monday, March 19, 2012 6:03 PM