##Cxx.jl
The Julia C++ Foreign Function Interface (FFI).
You will need to install Julia v0.4-dev with some special options.
Cxx.jl requires "staged functions" amongst other things available only in v0.4. It also requires the development version of LLVM, which is currently targeting version 3.7.
In addition to the system requirements to build julia itself, the following are required:
- Debian/Ubuntu:
libedit-dev
,libncurses5-dev
- RedHat/CentOS:
libedit-devel
Get the latest git checkout from https://github.com/JuliaLang/julia.git then add (or add to) a Make.user
file at the top level with the following lines:
override LLDB_VER=master
override LLVM_VER=svn
override LLVM_ASSERTIONS=1
override BUILD_LLVM_CLANG=1
override BUILD_LLDB=1
override USE_LLVM_SHLIB=1
override LLDB_DISABLE_PYTHON=1
Then build simply with make
.
Test your build of julia with make testall
.
Optionally, also build the debug build of julia with make debug
. If available, this will be used in the next step.
Launch the julia you just built, and in the terminal type
Pkg.clone("https://github.com/Keno/Cxx.jl.git")
Pkg.build("Cxx")
The main interface provided by Cxx.jl is the @cxx macro. It supports two main usages:
- Static function call @cxx mynamespace::func(args...)
- Membercall (where m is a CppPtr, CppRef or CppValue) @cxx m->foo(args...)
To embedd C++ functions in Julia, there are two main approaches:
# Using @cxx (e.g.):
cxx""" void cppfunction(args){ . . .} """ => @cxx cppfunction(args)
# Using icxx (e.g.):
julia_function (args) icxx""" *code here* """ end
This package contains an experimental C++ REPL feature. Using the package
will automatically add a new pane to your REPL that is accessible by pressing the
<
key.
# include headers
julia> using Cxx
julia> cxx""" #include<iostream> """
# Declare the function
julia> cxx"""
void mycppfunction() {
int z = 0;
int y = 5;
int x = 10;
z = x*y + 2;
std::cout << "The number is " << z << std::endl;
}
"""
# Convert C++ to Julia function
julia> julia_function() = @cxx mycppfunction()
julia_function (generic function with 1 method)
# Run the function
julia> julia_function()
The number is 52
julia> jnum = 10
10
julia> cxx"""
void printme(int x) {
std::cout << x << std::endl;
}
"""
julia> @cxx printme(jnum)
10
julia> cxx"""
void printme(const char *name) {
// const char* => std::string
std::string sname = name;
// print it out
std::cout << sname << std::endl;
}
"""
julia> @cxx printme(pointer("John"))
John
julia> cxx"""
void testJuliaPrint() {
$:(println("\nTo end this test, press any key")::Nothing);
}
"""
julia> @cxx testJuliaPrint()
To end this test, press any key
function playing()
for i = 1:5
icxx"""
int tellme;
std::cout<< "Please enter a number: " << std::endl;
std::cin >> tellme;
std::cout<< "\nYour number is "<< tellme << "\n" <<std::endl;
"""
end
end
playing();
julia> cxx"""
class Klassy {
public:
enum Foo { Bar, Baz };
static Foo exec(Foo x) { return x; }
};
"""
# Access enum
julia> @cxx Klassy::Bar
CppEnum{symbol("Klassy::Foo")}(0)
# Pass enum as an argument
julia> @cxx Klassy::exec(@cxx(Klassy::Baz))
CppEnum{symbol("Klassy::Foo")}(1)
julia> using Cxx
julia> cxx"""#include <iostream>
class Hello
{
public:
void hello_world(const char *now){
std::string snow = now;
std::cout << "Hello World! Now is " << snow << std::endl;
}
};"""
julia> hello_class = @cxxnew Hello()
julia> tstamp = string(Dates.now())
julia> @cxx hello_class -> hello_world(pointer(tstamp))
Hello World! Now is 2015-06-19T11:20:31
ArrayMaker.h
#ifndef ARRAYMAKER_H
#define ARRAYMAKER_H
class ArrayMaker
{
private:
int iNumber;
float fNumber;
float* fArr;
public:
ArrayMaker(int, float);
float* fillArr();
};
#endif
ArrayMaker.cpp
#include "ArrayMaker.h"
#include <iostream>
using namespace std;
ArrayMaker::ArrayMaker(int iNum, float fNum) {
cout << "Got arguments: " << iNum << ", and " << fNum << endl;
iNumber = iNum;
fNumber = fNum;
fArr = new float[iNumber];
}
float* ArrayMaker::fillArr() {
cout << "Filling the array" << endl;
for (int i=0; i < iNumber; i++) {
fArr[i] = fNumber;
fNumber *= 2;
}
return fArr;
}
Compiling into shared library
>> g++ -shared -fPIC ArrayMaker.cpp -o libArrayMaker.so
Using in Julia
julia> using Cxx
# Importing shared library and header file
julia> const path_to_lib = pwd()
julia> addHeaderDir(path_to_lib, kind=C_System)
julia> Libdl.dlopen(path_to_lib * "/libArrayMaker.so", Libdl.RTLD_GLOBAL)
Ptr{Void} @0x000000000728e6d0
julia> cxxinclude("ArrayMaker.h")
# Creating class object
julia> maker = @cxxnew ArrayMaker(5, 2.0)
Got arguments: 5, and 2
Cxx.CppPtr{Cxx.CppValue{Cxx.CppBaseType{:ArrayMaker},(false,false,false)},(false,false,false)}(Ptr{Void} @0x00000000060ab570)
julia> arr = @cxx maker->fillArr()
Filling the array
julia> pointer_to_array(arr, 5)
5-element Array{Float32,1}:
2.0
4.0
8.0
16.0
32.0