Builing mathematica++

Requirements

  • Mathematica
  • cmake
  • git
  • c++ compiler
  • boost library

To build mathematica++ clone it from the git reposetory. The project in gitlab contains tests can can be verified using make test after make. mathematica++ is a regular cmake project that can be built as shown in the following snippet.

$ git clone https://gitlab.com/neel.basu/mathematicapp.git
$ cd mathematicapp
$ mkdir build
$ cd build
$ cmake ..
$ make

If you use CMake you can add mathematicapp as a subdirectory or you can check the test directory for some examples

Example Hello World projects

If you are new to CMake you may follow this example to set up a small C++ project that uses mathematica++ as a subproject. If you are new to CMake, this procedure can be followed to use any CMake based library as a subdir. Otherwise you may skip this section and follow your own path.

We will first set up an empty C++14 project using CMake. Let us keep it too simple and name is MyProject1. The name of the executable would be myproject1. We will create a directory for our project and create a main.cpp file into it. We will also create a CMakeLists.txt for our project. The latest version of mathematica++ is cloned from git inside the project.

$ mkdir MyProject1
$ cd MyProject1
$ touch CMakeLists.txt
$ touch main.cpp
$ git clone https://gitlab.com/neel.basu/mathematicapp.git

We set the compiler options to use C++14 for our project. There can be many ways to do that. These are some interesting posts related to this. However following is an example CMakeLists.txt that you can just copy paste into. Notice ADD_SUBDIRECTORY(mathematicapp). MYPROJECT_SOURCES is where you put all your source cpp files. TARGET_LINK_LIBRARIES links the executable with the library.

CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
PROJECT(myproject1)

MACRO(USE_CXX11)
  IF(CMAKE_VERSION VERSION_LESS "3.1")
    IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      SET(CMAKE_CXX_FLAGS "--std=gnu++14 ${CMAKE_CXX_FLAGS}")
    ENDIF()
  ELSE()
    SET(CMAKE_CXX_STANDARD 14)
  ENDIF()
ENDMACRO(USE_CXX11)

USE_CXX11()

SET(CMAKE_CXX_FLAGS "-ftemplate-backtrace-limit=0 ${CMAKE_CXX_FLAGS}")

ADD_SUBDIRECTORY(mathematicapp)

SET(MYPROJECT_SOURCES
    main.cpp
)

ADD_EXECUTABLE(myproject1 ${MYPROJECT_SOURCES})
TARGET_LINK_LIBRARIES(myproject1 mathematica++)

Lets put some code into our main.cpp

#include <iostream>
#include <mathematica++/mathematica++.h>

using namespace mathematica;

int main(){
    connector shell;
    if(shell.connected()){
        std::cout << "connected to Mathematica !!" << std::endl;
    }

    return 0;
}

Let us build our myproject1. We will create a directory build inside MyProject1

$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./myproject1

myproject1 is teh executable created. If everyting goes well you shoudl see teh following output.

$ ./myproject1 
connected to Mathematica !!

But we didn't call a mathematica function yet. Lets do that now.

Calling Mathematica Function from C++

Let the first Mathematica function be Divisors. First we need to tell!! C++ that the name Divisors exists using the MATHEMATICA_DECLARE macro.

MATHEMATICA_DECLARE(Divisors)

Now we need to call that mathematica function Divisors. That is the goal of this entire work. So we simply call it just as we call any other function.

shell << Divisors(1729);

Thats it. We have called the mathematica function. I have choosen the number 1729 just because this number is there in the wolfram reference. Nothing special. But we still need to get the output from the mathematica and store it somewhere. Lets store it in result.

value result;

Now we need to fetch the output from mathematica and store it in result.

shell >> result;

Thats it. We now have the output. So lets print it.

std::cout << result << std::endll;

Now make again. If everything goes well this is the expected output.

List[1, 7, 13, 19, 91, 133, 247, 1729]

But what to do with it ? It is just a string. Hm. So lets have a std::vector<int>

typedef std::vector<int> divisors_type;
divisors_type divisors;

Now we need to parse that result into our divisors. Lets cast it.

divisors = cast<divisors_type>(result);

We are done. Lets print it.

for(int n: divisors){
    std::cout << n << std::endl;
}

Prints the following.

1
7
13
19
91
133
247
1729

Hallo World !! This is complete code you just want to copy paste and give it a try.

#include <iostream>
#include <mathematica++/mathematica++.h>

using namespace mathematica;

MATHEMATICA_DECLARE(Divisors)

int main(){
    connector shell;
    if(!shell.connected()){
        std::cout << "Failed to connect to Mathematica !!" << std::endl;
        return 1;
    }

    value result;

    shell << Divisors(1729);
    shell >> result;

    std::cout << result << std::endl;

    typedef std::vector<int> divisors_type;
    divisors_type divisors;

    divisors = cast<divisors_type>(result);

    for(int n: divisors){
        std::cout << n << std::endl;
    }


    return 0;
}