1

I'm trying to write a simple application to get acquainted with dll projects in C++. I've followed the example at MSDN first: http://msdn.microsoft.com/en-us/library/ms235636(v=vs.90).aspx

It works well, so I tried one step further. Here is my code:

// MathFuncsDll.h
#include <vector>

namespace MathFuncs
{
// This class is exported from the MathFuncsDll.dll
    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 const std::invalid_argument& if b is 0
        static __declspec(dllexport) double Divide(double a, double b); 

        static __declspec(dllexport) double Sumproduct(vector<double>* a, vector<double>* b);
        // **Here I use std::vector** 
};

}

And in MathFuncsDll.cpp:

// MathFuncsDll.cpp : Defines the exported functions for the DLL application. 

#include "stdafx.h"
#include "MathFuncsDll.h"
#include <stdexcept>
#include <vector>

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 invalid_argument("b cannot be zero!");
        }

        return a / b;
    }

    // **Here is the definition of Sumproduct**     
    double MyMathFuncs::Sumproduct(vector<double>* a, vector<double>* b)
    {
        int size1 = a->size(), size2 = b->size();
        if(size1 != size2)
        {
            throw invalid_argument("The length of input vectors should be the same!");
        }

        double sum = 0;
        for(int i = 0; i < size1; i++)
            sum += a->at(i) * b->at(i);

        return sum;
    }
}

And in main:

// MyExecRefsDll.cpp 
// compile with: /EHsc /link MathFuncsDll.lib

#include <iostream>

#include "MathFuncsDll.h" 

using namespace std;

int main()
{
    double a = 7.4;
    int b = 99;

    cout << "a + b = " <<
        MathFuncs::MyMathFuncs::Add(a, b) << endl;
    cout << "a - b = " <<
        MathFuncs::MyMathFuncs::Subtract(a, b) << endl;
    cout << "a * b = " <<
        MathFuncs::MyMathFuncs::Multiply(a, b) << endl;
    cout << "a / b = " <<
        MathFuncs::MyMathFuncs::Divide(a, b) << endl;

    try
    {
        cout << "a / 0 = " <<
            MathFuncs::MyMathFuncs::Divide(a, 0) << endl; 
    }
    catch (const invalid_argument &e) 
    {
        cout << "Caught exception: " << e.what() << endl; 
    }

    system("pause");

    return 0;
}

When I try to build the solution with VS2012, it gives following error messages

error C2511: 'double MathFuncs::MyMathFuncs::Sumproduct(std::vector<_Ty> *,std::vector<_Ty> *)' : overloaded member function not found in 'MathFuncs::MyMathFuncs'

error C2061: syntax error : identifier 'vector'

I am very new to dll projects, so please forgive my ignorance. May I know what am I wrong?

Many thanks in advance.

=============================================================

EDIT1:

I think it could be easier to find an answer by giving a big picture. I am planning to write some .dll files and call them from Python code. As @Chad suggest, it is not a good idea to do in the above approach since it will force the user (which is me) to use the same implementation as STL.

Then, may I know, in order to achieve my plan, if there is a better way to do it?

Thank you very much. :)

==============================================================

EDIT2:

Thanks to all for your kind help. Especially thanks to @Anodyne. Now my origin question is perfectly answered by Anodyne. However, as I stated in EDIT1, now I have to consider for future cooperation between C++ dll and Python.

Any suggestions will be welcome! Many thanks again! :)

PS: should I open a new thread for this?

ChangeMyName
  • 7,018
  • 14
  • 56
  • 93
  • 1
    missing namespace std in header - use std::vector instead of vector in header. – Tom Sep 11 '13 at 14:14
  • The error is given when compiling the dll or the main project ? – Raxvan Sep 11 '13 at 14:14
  • @Raxvan Thanks for your reply. It happens when I try to run main project. – ChangeMyName Sep 11 '13 at 14:19
  • @Tom Thanks for the suggestion. I've tried it. But seems more errors are coming up. The new one I've got is `error C2039: 'vector' : is not a member of 'std'`. This is strange, since we all know that `vector` is absolutely a member of `std`... – ChangeMyName Sep 11 '13 at 14:21
  • 4
    I would suggest avoiding `C++` in the interface of your DLL. You can of course use it internally, but sending `C++` classes across a DLL boundary can have a significant impact on users of your library -- forcing them to use the same STL implementation (which likely means the same compiler version, and C runtime). (related: http://stackoverflow.com/questions/5107948/throwing-c-exceptions-across-dll-boundaries) – Chad Sep 11 '13 at 14:24
  • @Chad Thanks. I think you are making a very important point. Because I am planning to write some .dll files and call them from Python. I've googled before I ask, so I've heard about "passing C++ class across DLL boundary is a big problem" a lot. May I have a clue that how can I achieve my goal? Many thanks in advance. :) – ChangeMyName Sep 11 '13 at 14:28
  • 2
    I've written about the problems of using C++ stuff in DLL interfaces here: http://www.lenholgate.com/blog/2005/06/working-on-the-borders.html You can usually work around it by a) avoiding STL in the interface and b) using standard C linkage to a factory method which returns a pure virtual "interface" class (after all, this is how COM does it). – Len Holgate Sep 11 '13 at 14:40
  • I agree with everyone else to avoid STL in your DLL. Especially in this case, just take `(double *, double *, size_t)`. Users can still work with `std::vector` and pass in `v1.data(), v2,data(), v1.size()` for your DLL. – japreiss Sep 11 '13 at 14:44
  • @japreiss That looks very promising. Can you show me more details? it would be great if you can write a simple snippet. Many thanks. :) – ChangeMyName Sep 11 '13 at 14:58

2 Answers2

1

I haven't tried compiling your code, but I've spotted one problem: in MathFuncsDll.h, you're referring to the "std::vector" class as just "vector" - this should be "std::vector". In other words, the last declaration in MathFuncsDll.h should look like this:

    static __declspec(dllexport) double Sumproduct(std::vector<double>* a, std::vector<double>* b);

You might have other problems as well, of course :-)

Anodyne
  • 1,760
  • 2
  • 15
  • 28
  • Thanks for the suggestion. I've tried it. But seems more errors are coming up. The new one I've got is `error C2039: 'vector' : is not a member of 'std'`. This is strange, since we all know that `vector` is absolutely a member of `std`... – ChangeMyName Sep 11 '13 at 14:22
  • I've now tried compiling your code (albeit with VS2010) and I'm not seeing that error. Is the code you're compiling identical to the code you posted? – Anodyne Sep 11 '13 at 14:50
  • Yes, I direct copy it from my IDE. – ChangeMyName Sep 11 '13 at 14:52
  • The error suggests that you've forgotten to #include in MathFuncsDll.h. – Anodyne Sep 11 '13 at 14:56
  • That's weired. cos `#include ` is waving to me in MathFuncsDll.h. T_T – ChangeMyName Sep 11 '13 at 15:03
1

Boost.Python seems to be exactly what you're looking for. I haven't tried it myself (not being a Pythonista), but I use other Boost libraries all the time and they're uniformly great.

Anodyne
  • 1,760
  • 2
  • 15
  • 28