2

As a complete novice with C++ I just created my first Dynamic Link Library following the MS tutorial found here

The header file reads as follows:

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

Now, I want to read this file into Python ctypes. I do this using:

import ctypes as ctypes

MyDll = 'MathFuncsDll.dll'
MyFuncs = ctypes.cdll.LoadLibrary(MyDll)

Now, I'm struggling to actually access the functions. My intuition leads me to try

a = ctypes.c_double(54)
b = ctypes.c_double(12)

summation = MyFuncs.Add(a,b)

which returns the error

AttributeError: function 'Add' not found

Is my problem that the function is nested within the class MyMathFuncs which is also within namespace MathFuncs? How do I gain access to these functions?

For reference, below is the contents of the .cpp file used to generate the dll

// 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;
    }
}
Joe
  • 355
  • 1
  • 5
  • 17

1 Answers1

3

You cannot access C++ classes and namespaces using the ctypes. There is no standard binary interface for C++, as there is for C. Every compiler outputs it's own (different) binaries for the same C++ dynamic libraries. You can read more about it here.

The thing you can do (if you have to do it in C++) is do all your work in C++ and then write a tiny layer of C that wraps it and exposes it. Then you'll be able to access it using ctypes. Again, you can read about it here

Community
  • 1
  • 1
Viktor Kerkez
  • 45,070
  • 12
  • 104
  • 85
  • This is helpful. Thanks. Do you know if there is a straightforward way to make a "C" DLL as opposed to a "C++" DLL? What is inherently C++ about this DLL (other than using a C++ compiler, of course). – Joe Aug 09 '13 at 16:58
  • Not sure what is your question exactly? You can make a C DLL compiling C code with a C compiler or exposing C++ code using `extern "C" {`. DLL's have their binary interface, but different C++ compilers, unfortunately, output different binaries for the same C++ code, due to name handling and/or different ways to manage the stack between library function calls. – Viktor Kerkez Aug 09 '13 at 21:53
  • Hmm... so what exactly would you enclose in the extern C brackets? Do you need to do make similar adjustments for both the cpp and the header file? – Joe Aug 09 '13 at 23:02
  • This is a bit offtopic. And it's explained in a lot of places on [stackoverflow](http://stackoverflow.com/questions/2045774/developing-c-wrapper-api-for-object-oriented-c-code) and [many](http://www.tldp.org/HOWTO/C++-dlopen/thesolution.html) [other](http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/) [places](http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B)... – Viktor Kerkez Aug 09 '13 at 23:25