├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── c └── main.c ├── c_sharp └── main.cs ├── go └── main.go ├── haskell └── main.hs ├── nim └── main.nim ├── node └── main.js ├── python └── main.py ├── ruby └── main.rb └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | *.o 4 | main 5 | *.pyc 6 | *.hi 7 | *.exe 8 | /node_modules 9 | nimcache/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: rust 3 | rust: 4 | - stable 5 | - beta 6 | - nightly 7 | env: 8 | - CXX=g++-4.8 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | packages: 14 | - gcc-4.8 15 | - g++-4.8 16 | - ghc 17 | - python3 18 | go: 19 | - tip 20 | install: 21 | - wget http://nim-lang.org/download/nim-0.12.0.tar.xz 22 | - tar xf nim-0.12.0.tar.xz 23 | - cd nim-0.12.0 24 | - sh build.sh 25 | - cd .. 26 | - export PATH=`pwd`/nim-0.12.0/bin:$PATH 27 | - nvm install stable 28 | - nvm use stable 29 | - npm install ffi glob 30 | - gem install ffi 31 | script: 32 | - cargo build 33 | - cd c && gcc main.c -L ../target/debug -lstringtools -o main && LD_LIBRARY_PATH=../target/debug ./main 34 | - cd ../haskell && ghc --make main.hs -L../target/debug -lstringtools -o main && LD_LIBRARY_PATH=../target/debug ./main 35 | - cd ../go && LD_LIBRARY_PATH=../target/debug go run main.go 36 | - cd ../python && python3 main.py 37 | - cd ../nim && nim c -r --verbosity:0 main.nim 38 | - cd ../node && node main.js 39 | - cd ../ruby && ruby main.rb 40 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "stringtools" 4 | version = "0.0.1" 5 | authors = ["Zbigniew Siciarz "] 6 | 7 | [lib] 8 | name = "stringtools" 9 | crate-type = ["dylib"] 10 | 11 | [dependencies] 12 | libc = "~0.1" 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Zbigniew Siciarz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: c c_sharp go haskell nim node python ruby clean 2 | 3 | all: c c_sharp go haskell nim node python ruby 4 | 5 | lib: 6 | cargo build 7 | 8 | export LD_LIBRARY_PATH=../target/debug 9 | 10 | c: lib 11 | cd c && gcc main.c -L ../target/debug -lstringtools -o main && ./main 12 | 13 | c_sharp: lib 14 | cd c_sharp && mcs main.cs && mono main.exe 15 | 16 | go: lib 17 | cd go && go run main.go 18 | 19 | haskell: lib 20 | cd haskell && ghc --make main.hs -L../target/debug -lstringtools -o main && ./main 21 | 22 | nim: lib 23 | cd nim && nim c -r --verbosity:0 main.nim 24 | 25 | node: lib 26 | cd node && node main.js 27 | 28 | python: lib 29 | cd python && python3 main.py 30 | 31 | ruby: lib 32 | cd ruby && ruby main.rb 33 | 34 | clean: 35 | cargo clean && rm c/main c_sharp/main.exe haskell/main 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rust-ffi-stringtools 2 | ==================== 3 | 4 | [![Build Status](https://travis-ci.org/zsiciarz/rust-ffi-stringtools.svg?branch=master)](https://travis-ci.org/zsiciarz/rust-ffi-stringtools) 5 | 6 | A collection of examples how to use Rust libraries from other languages. 7 | 8 | Works on Rust 1.0 stable. 9 | 10 | Author 11 | ====== 12 | 13 | * Zbigniew Siciarz (zbigniew at siciarz dot net) 14 | 15 | License 16 | ======= 17 | 18 | This work is released under the MIT license. A copy of the license is provided 19 | in the LICENSE file. 20 | -------------------------------------------------------------------------------- /c/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int32_t count_substrings(const char* value, const char* substr); 5 | 6 | int main() { 7 | printf("%d\n", count_substrings("bąnana", "na")); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /c_sharp/main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | public class StringTools 5 | { 6 | [DllImport("../target/debug/libstringtools.so")] 7 | public static extern Int32 count_substrings(string value, string substr); 8 | 9 | static public void Main() 10 | { 11 | Console.WriteLine(count_substrings("bąnana", "na")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // #cgo LDFLAGS: -L../target/debug -lstringtools 4 | // int count_substrings(const char* value, const char* substr); 5 | import "C" 6 | import "fmt" 7 | 8 | func main() { 9 | value := C.CString("bąnana") 10 | substr := C.CString("na") 11 | fmt.Println(C.count_substrings(value, substr)) 12 | } 13 | -------------------------------------------------------------------------------- /haskell/main.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ForeignFunctionInterface #-} 2 | 3 | import Foreign.C.String (CString, newCString) 4 | 5 | foreign import ccall "count_substrings" 6 | count_substrings :: CString -> CString -> IO Int 7 | 8 | main :: IO () 9 | main = do 10 | value <- newCString "bąnana" 11 | substr <- newCString "na" 12 | count_substrings value substr >>= print 13 | -------------------------------------------------------------------------------- /nim/main.nim: -------------------------------------------------------------------------------- 1 | proc count_substrings(value: cstring, substr: cstring): cint 2 | {.cdecl, importc, dynlib: "../target/debug/libstringtools.so".} 3 | 4 | echo(count_substrings("bąnana", "na")) 5 | -------------------------------------------------------------------------------- /node/main.js: -------------------------------------------------------------------------------- 1 | var ffi = require('ffi'); 2 | 3 | var library_name = '../target/debug/libstringtools.so'; 4 | var stringtools = ffi.Library(library_name, { 5 | 'count_substrings': ['int', ['string', 'string']] 6 | }); 7 | 8 | console.log(stringtools.count_substrings("bąnana", "na")); 9 | -------------------------------------------------------------------------------- /python/main.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | 3 | library_name = "../target/debug/libstringtools.so" 4 | stringtools = ctypes.CDLL(library_name) 5 | print(stringtools.count_substrings("bąnana".encode('utf-8'), b"na")) 6 | -------------------------------------------------------------------------------- /ruby/main.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # 3 | require 'ffi' 4 | 5 | module StringTools 6 | extend FFI::Library 7 | ffi_lib "../target/debug/libstringtools.so" 8 | attach_function :count_substrings, [:string, :string], :int 9 | end 10 | 11 | puts StringTools.count_substrings("bąnana", "na") 12 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate libc; 2 | 3 | use std::ffi::CStr; 4 | use std::str; 5 | use libc::c_char; 6 | 7 | #[no_mangle] 8 | pub extern "C" fn count_substrings(value: *const c_char, substr: *const c_char) -> i32 { 9 | let c_value = unsafe { CStr::from_ptr(value).to_bytes() }; 10 | let c_substr = unsafe { CStr::from_ptr(substr).to_bytes() }; 11 | match str::from_utf8(c_value) { 12 | Ok(value) => match str::from_utf8(c_substr) { 13 | Ok(substr) => rust_substrings(value, substr), 14 | Err(_) => -1, 15 | }, 16 | Err(_) => -1, 17 | } 18 | } 19 | 20 | fn rust_substrings(value: &str, substr: &str) -> i32 { 21 | value.matches(substr).count() as i32 22 | } 23 | --------------------------------------------------------------------------------