Julia Cxx
This notebook creates a reusable environment with Julia's Cxx package installed in the setup section, and shows off basic usage of the package in the showcase.
Showcase
Adapted from the Cxx examples to show usage of the package on Nextjournal—redistributed under the MIT Expat License.
The Cxx package is Julia's Foreign Function Interface to C++. With it, you can include C++ functions and constructs in Julia code, use shared libraries, and pass data between the two languages.
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
mis aCppPtr,CppReforCppValue)@cxx m->foo(args...)
To embed C++ functions in Julia, there are two main approaches:
# Using @cxx (e.g.): cxx""" void cppfunction(args){ . . .} """ => cppfunction(args)# Using icxx (e.g.): julia_function (args) icxx""" *code here* """ endEmbedding a simple C++ function in Julia
# include headersusing Cxxcxx""" #include<iostream> """ # Declare the functioncxx""" 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 functionjulia_function() = mycppfunction()Run the function.
julia_function()Pass numeric arguments from Julia to C++
jnum = 10cxx""" void printme(int x) { std::cout << x << std::endl; }""" printme(jnum)Pass strings from Julia to C++
cxx""" void printme(const char *name) { // const char* => std::string std::string sname = name; // print it out std::cout << sname << std::endl; }""" printme(pointer("John"))Pass a Julia expression to C++
cxx""" void testJuliaPrint() { $:(println("\nHello whirled!")::Nothing); }""" testJuliaPrint()Embedding C++ code inside a Julia function
using Cxxcxx""" #include <iostream> """ 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; """ endendNextjournal tries to pass values when it detects a pause for interactive input.
playing();Using C++ enums
using Cxxcxx""" class Klassy { public: enum Foo { Bar, Baz }; static Foo exec(Foo x) { return x; } };"""Access enum
Klassy::BarPass enum as an argument
Klassy::exec((Klassy::Baz))C++ Hello World class
using Cxxcxx"""#include <iostream> class Hello { public: void hello_world(const char *now){ std::string snow = now; std::cout << "Hello World! Now is " << snow << std::endl; } };"""using Dateshello_class = Hello()tstamp = string(Dates.now()) hello_class -> hello_world(pointer(tstamp))Using C++ with shared libraries
The two code listings below are named, and mounted to the runtime as files.
#ifndef ARRAYMAKER_H#define ARRAYMAKER_Hclass ArrayMaker{ private: int iNumber; float fNumber; float* fArr; public: ArrayMaker(int, float); float* fillArr();};#endif#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.soImporting shared library and header file.
using Cxx, Libdlconst path_to_lib = pwd()addHeaderDir(path_to_lib, kind=C_System)Libdl.dlopen(path_to_lib * "/libArrayMaker.so", Libdl.RTLD_GLOBAL)cxxinclude("ArrayMaker.h")Creating class object
# Creating class objectmaker = ArrayMaker(5, 2.0)arr = maker->fillArr()unsafe_wrap(Array, arr, 5)Setup
Install Cxx.
]up]add Cxx]precompile]test Cxx