Skip to content

Commit

Permalink
Add wrap_module function to allow adding Julia code to a module
Browse files Browse the repository at this point in the history
  • Loading branch information
barche committed Apr 1, 2016
1 parent 2489ff2 commit ea74742
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 7 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ cxx_wrap::create<Class>(constructor_arg1, ...);
```
This will return the new C++ object wrapped in a `jl_value_t*` that has a finalizer.

## Adding Julia code to the module
Sometimes, you may want to write additional Julia code in the module that is built from C++. To do this, call the `wrap_module` method inside an appropriately named Julia module:
```julia
module ExtendedTypes

using CxxWrap
wrap_module(joinpath(Pkg.dir("CxxWrap"),"deps","usr","lib","libextended"))
export ExtendedWorld, greet

end
```
Here, `ExtendedTypes` is a name that matches the module name passed to `create_module` on the C++ side. The `wrap_module` call works as before, but now the functions and types are defined in the existing `ExtendedTypes` module, and additional Julia code such as exports and macros can be defined.

## Linking with the C++ library
The library (in [`deps/src/cxx_wrap`](deps/src/cxx_wrap)) is built using CMake, so it can be found from another CMake project using the following line in a `CMakeLists.txt`:

Expand Down
2 changes: 1 addition & 1 deletion deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ provides(BuildProcess,
end),examples)

deps = [cxx_wrap, examples]
provides(Binaries, Dict(URI("https://github.com/barche/CxxWrap.jl/releases/download/v0.1.0/CxxWrap.zip") => deps), os = :Windows)
provides(Binaries, Dict(URI("https://github.com/barche/CxxWrap.jl/releases/download/v0.1.2/CxxWrap.zip") => deps), os = :Windows)

@BinDeps.install

Expand Down
4 changes: 4 additions & 0 deletions deps/src/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ target_link_libraries(inheritance CxxWrap::cxx_wrap)
add_library(parametric SHARED parametric.cpp)
target_link_libraries(parametric CxxWrap::cxx_wrap)

add_library(extended SHARED extended.cpp)
target_link_libraries(extended CxxWrap::cxx_wrap)

install(TARGETS
extended
functions
hello
inheritance
Expand Down
25 changes: 25 additions & 0 deletions deps/src/examples/extended.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <string>

#include <cxx_wrap.hpp>

namespace extended
{

struct ExtendedWorld
{
ExtendedWorld(const std::string& message = "default hello") : msg(message){}
std::string greet() { return msg; }
std::string msg;
};

} // namespace extended

JULIA_CPP_MODULE_BEGIN(registry)
using namespace extended;

cxx_wrap::Module& types = registry.create_module("ExtendedTypes");

types.add_type<ExtendedWorld>("ExtendedWorld")
.method("greet", &ExtendedWorld::greet);

JULIA_CPP_MODULE_END
33 changes: 27 additions & 6 deletions src/CxxWrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,6 @@ function wrap_functions(functions, julia_mod)
end
end

# Wrap all functions, placing the wrapper in the current module
function wrap_functions(functions)
wrap_functions(functions, current_module())
end

# Create modules defined in the given library, wrapping all their functions and types
function wrap_modules(registry::Ptr{Void}, parent_mod=Main)
module_names = get_module_names(registry)
Expand Down Expand Up @@ -180,6 +175,32 @@ function wrap_modules(so_path::AbstractString, parent_mod=Main)
wrap_modules(registry, parent_mod)
end

export wrap_modules
# Place the functions and types into the current module
function wrap_module(so_path::AbstractString, parent_mod=Main)
registry = CxxWrap.load_modules(lib_path(so_path))
module_names = get_module_names(registry)
mod_idx = 0
wanted_name = string(module_name(current_module()))
for (i,mod_name) in enumerate(module_names)
if mod_name == wanted_name
bind_types(registry, current_module())
mod_idx = i
break
end
end

if mod_idx == 0
error("Module $wanted_name not found in C++")
end

module_functions = get_module_functions(registry)
wrap_functions(module_functions[mod_idx], current_module())

exps = [symbol(s) for s in exported_symbols(registry, wanted_name)]
current_module().eval(:(export $(exps...)))
end


export wrap_modules, wrap_module

end # module
19 changes: 19 additions & 0 deletions test/extended_module.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Example on how to load types and methods from C++ into an existing module

println("Running extended_module.jl...")
using Base.Test

module ExtendedTypes

using CxxWrap

wrap_module(joinpath(Pkg.dir("CxxWrap"),"deps","usr","lib","libextended"))

export ExtendedWorld, greet

end

using ExtendedTypes

w = ExtendedWorld()
@test greet(w) == "default hello"
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ include("types.jl")
include("inheritance.jl")
include("parametric.jl")
include("property.jl")
include("extended_module.jl")

0 comments on commit ea74742

Please sign in to comment.