Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The Problem.

I have a C++ class that does some computations, and returns a C++ vector object (the length of which can possibly vary with each run).

I want to store each of these vectors as a list in Mathematica, so, for instance, if three iterations returns the vectors (0, 1), (0.02, 0.9) and (0.04, 0.73), I want this output to be written into a Mathematica list of the form {{0,1},{0.02, 0.9},{0.04, 0.73}}.

My limitations.

This is the first time I am trying to mess with MathLink. Having spent all of today trying to get this to work, I'm feeling pretty lost. The documentation that has shipped with my Mathematica distribution, is helpful only in that I know what to do to write most of the template file. But I can't quite understand how to finish it, and what to do next.

Operating System and other information

I am on a Mac running Snow Leopard 10.6.8. Mathematica is installed in the usual place: /Applications/Mathematica.app

Code

First, what I believe are the relevant portions of the C++ code that I already have

#include<iostream>
#include<vector>
#include<deque>
#include<cmath>
// and a bunch of other files

class mp{


// stuff that defines the class
public:

// some functions
vector <long double> viewCurrent(); // returns the (t, x) vector for the current state of the
                                    // system; note that x can be a vector itself

};

What I would like is to store the output of mp::viewCurrent() into Mathematica lists. How do I do this?

share|improve this question
    
Your life will greatly be simplified if you are willing to use double instead of long double. –  Szabolcs Jul 23 '12 at 6:41
    
It seems that what you are asking for is an example of how to access from Mathematica a function that returns variable length vectors. Here's an example for LibraryLink. –  Szabolcs Jul 23 '12 at 6:44
    
Thanks for linking to LibraryLink. Let's see if I can get this working. –  Y.P. Jul 23 '12 at 13:17
add comment

2 Answers

up vote 3 down vote accepted

Then let me give you a minimal example using LibraryLink. Create a file named my_vector.cpp (it is in my "tmp" folder here).

#include "mathlink.h"
#include "WolframLibrary.h"
#include <vector>

DLLEXPORT mint WolframLibrary_getVersion(){
  return WolframLibraryVersion;
}

DLLEXPORT int WolframLibrary_initialize( WolframLibraryData libData)
{
  return 0;
}

DLLEXPORT void WolframLibrary_uninitialize( WolframLibraryData libData) 
{
  return;
}

EXTERN_C DLLEXPORT int vectortest(WolframLibraryData libData, MLINK mlp)
{

  using std::vector;
  long len;
  vector<int> vec;

  MLCheckFunction(mlp, "List", &len);
  if (len != 0) {
    libData->Message("0 arguments expected.");
    return LIBRARY_FUNCTION_ERROR;
  }
  MLNewPacket(mlp);

  for (int iter = 0; iter < 10; ++iter) {
    vec.push_back(iter);
  }

  vector<int>::iterator it;

  MLPutFunction(mlp,"List", vec.size());
  for (it = vec.begin(); it < vec.end(); ++it) {
    MLPutInteger(mlp, *it);
  }  
  return LIBRARY_NO_ERROR;
}

Now open a Mathematica and compile it. This assumes, that you have a running c-compiler which is recognized by Mathematica

<< CCompilerDriver`
CreateLibrary[{"tmp/my_vector.cpp"}, "my_vector", 
 "ShellOutputFunction" :> Print, "ShellCommandFunction" :> Print]

The options are not necessary, but it helps when you see the compilation messages and the command-line. Mathematica places the ready to use dll|so|dylib in a folder in the search-path. Now, you can load it directly:

vecf = LibraryFunctionLoad["my_vector", "vectortest", LinkObject, LinkObject];
vecf[]

(*
  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
*)
share|improve this answer
    
This is exactly what I was looking for, and is so much more illustrative than the documentation out there! Thank you so much. –  Y.P. Jul 25 '12 at 5:58
add comment

I am posting here because the comments field is too small to contain this. This really should be in the comments, though.

I think I have a solution that works for the particular question I asked. However, I haven't yet gotten LibraryLink to work. This is a MathLink based solution.

I am posting the appropriate snippets of code here.

The template file

I will call my template file template.tm

:Begin:
:Function:      WrapperAroundClass
:Pattern:       Wrapper[Input1_Integer, Input2_Real, Input3_?NumberQ]
:Arguments:     {Input1, Input2, Input3}
:ArgumentTypes: {Manual}
:ReturnType:    Manual
:End:

I am only passing back lists from my c++ code to Mathematica. I am not sure how passing lists as inputs will work, though it might work the same way.

The c++ file

I will call my c++ file WrapperAroundClass.cpp

// include all the files needed here
#include "mp.h" // include the class I want to work with
#include "mathlink.h"

void WrapperAroundClass(){ // contains actual code

// fetch inputs from Mathematica
int Input1;
MLGetInteger(stdlink, &Input1); // fetch the others similarly
...
// finish fetching data

// do things with it

// now pass the data back
// class has a function mp::view_current() that returns a vector

vector<double> storage;

MLPutFunction(stdlink, "List", storage.size()); // tell mathematica a list of some size is 
                                                //coming
int j = 0;
while(j < storage.size()){ 
    MLPutDouble(stdlink, storage.at(j)); // pass the list element by element
    j++;
}
}

// write the default main function
int main(int argc, char* argv[]){
    return MLMain(argc, argv);
}

In the example that I have posted here, storage has depth 1. Multiple depths can be handled in the obvious way; I am not sure if this is a terribly slow way of doing things.

To finish, now mprep the template file to get template.o, and compile WrapperAroundClass.cpp to get WrapperAroundClass.o. Finally use the C++ compiler to link them to create the executable.

Feed this to Mathematica using link = Import[myPath<>"WrapperAroundClass.out"] where myPath is a string that contains the path to where the executable resides. You will now have a function called Wrapper defined inside Mathematica.

Disclaimer

This is a brute force solution, and I am in no way pretending that this is elegant. I kind of like it though, because with minimal code changes it lets me pipe output to Mathematica.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.