diff --git a/.gitignore b/.gitignore
index ea8c4bf7f35f6f77f75d92ad8ce8349f6e81ddba..fb8fe3bdc30f6d1ba5dd0145584630f61debb0af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
 /target
+**/build
+**/.vscode
\ No newline at end of file
diff --git a/blockchain-sys/src/bindings.rs b/blockchain-sys/src/bindings.rs
index b6a150d91ecdd5f78697e18a9c16af33cc76704f..b9bf7077ca25aba5a2531fe70334a56dc3154c85 100644
--- a/blockchain-sys/src/bindings.rs
+++ b/blockchain-sys/src/bindings.rs
@@ -46,6 +46,53 @@ fn bindgen_test_layout_LibBcPayload() {
         )
     );
 }
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct LibBcCallback {
+    pub target: *mut ::std::os::raw::c_void,
+    pub callback: ::std::option::Option<
+        unsafe extern "C" fn(target: *mut ::std::os::raw::c_void, payload: LibBcPayload),
+    >,
+}
+#[test]
+fn bindgen_test_layout_LibBcCallback() {
+    assert_eq!(
+        ::std::mem::size_of::<LibBcCallback>(),
+        16usize,
+        concat!("Size of: ", stringify!(LibBcCallback))
+    );
+    assert_eq!(
+        ::std::mem::align_of::<LibBcCallback>(),
+        8usize,
+        concat!("Alignment of ", stringify!(LibBcCallback))
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<LibBcCallback>())).target as *const _ as usize },
+        0usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(LibBcCallback),
+            "::",
+            stringify!(target)
+        )
+    );
+    assert_eq!(
+        unsafe { &(*(::std::ptr::null::<LibBcCallback>())).callback as *const _ as usize },
+        8usize,
+        concat!(
+            "Offset of field: ",
+            stringify!(LibBcCallback),
+            "::",
+            stringify!(callback)
+        )
+    );
+}
+extern "C" {
+    pub fn libbc_callback_call(cb: *const LibBcCallback, payload: LibBcPayload);
+}
+extern "C" {
+    pub fn libbc_pass_callback(cb: LibBcCallback);
+}
 extern "C" {
     pub fn libbc_new_blockchain() -> *mut LibBcBlockchain;
 }
diff --git a/libblockchain/src/lib.cpp b/libblockchain/src/lib.cpp
index 60b5937e238e9b00106f27a7d82ad2adbba7c1ee..55480d0ab6d2b4bdd5004e3bd1c5363d47446fe4 100644
--- a/libblockchain/src/lib.cpp
+++ b/libblockchain/src/lib.cpp
@@ -4,42 +4,52 @@
 
 #include "lib.h"
 
-class LibBcBlockchain {
+class Blockchain {
 private:
     std::vector<std::string> data;
 
 public:
-    LibBcBlockchain();
+    Blockchain();
     void add_data(const std::string &&data);
     void print();
 };
 
-LibBcBlockchain::LibBcBlockchain() : data() {}
+Blockchain::Blockchain() : data() {}
 
-void LibBcBlockchain::add_data(const std::string &&data) {
+void Blockchain::add_data(const std::string &&data) {
     this->data.emplace_back(data);
 }
 
-LibBcBlockchain *libbc_new_blockchain() {
-    return new LibBcBlockchain();
+Blockchain *libbc_new_blockchain() {
+    return new Blockchain();
 }
 
-void LibBcBlockchain::print() {
+void Blockchain::print() {
     for (auto &data : this->data) {
         std::cout << data << std::endl;
     }
 }
 
-void libbc_blockchain_add(LibBcBlockchain *bc, uint64_t id, struct LibBcPayload payload) {
+void libbc_blockchain_add(Blockchain *bc, uint64_t id, struct LibBcPayload payload) {
     std::string s(payload.data, payload.data + payload.len);
     std::cout << "Added data " << id << " to Blockchain: " << s << std::endl;
     bc->add_data(std::move(s));
 }
 
-void libbc_blockchain_print(LibBcBlockchain *bc) {
+void libbc_blockchain_print(Blockchain *bc) {
     bc->print();
 }
 
-void libbc_delete_blockchain(LibBcBlockchain *bc) {
+void libbc_delete_blockchain(Blockchain *bc) {
     delete bc;
+}
+
+void libbc_callback_call(const struct LibBcCallback *cb, struct LibBcPayload payload) {
+    cb->callback(cb->target, payload);
+}
+
+void libbc_pass_callback(const struct LibBcCallback cb) {
+    LibBcPayload payload{(uint8_t *)"hello rust", 10};
+
+    libbc_callback_call(&cb, payload);
 }
\ No newline at end of file
diff --git a/libblockchain/src/lib.h b/libblockchain/src/lib.h
index 35a2b9d944a721db0b4f269f74c0c867e4697d2c..40071812a4bc5cae3cfdb7acb18ac178bb8c83f5 100644
--- a/libblockchain/src/lib.h
+++ b/libblockchain/src/lib.h
@@ -7,7 +7,7 @@
 
 // https://isocpp.org/wiki/faq/mixing-c-and-cpp#cpp-objs-passed-to-c
 #ifdef __cplusplus
-class LibBcBlockchain;
+typedef class Blockchain LibBcBlockchain;
 #else
 typedef struct LibBcBlockchain LibBcBlockchain;
 #endif
@@ -19,13 +19,22 @@ typedef struct LibBcBlockchain LibBcBlockchain;
 extern "C"
 {
 #endif
-
     struct LibBcPayload
     {
         const uint8_t *data;
         size_t len;
     };
 
+    // Our callback includes a target ("self" in Rust, "this" in C++) that store state (such as a channel) on the Rust side.
+    // target will be the first parameter to our callback function
+    struct LibBcCallback {
+        void *target;
+        void (*callback)(void *target, struct LibBcPayload payload);
+    };
+    void libbc_callback_call(const struct LibBcCallback *cb, struct LibBcPayload payload);
+    void libbc_pass_callback(const struct LibBcCallback cb);
+
+
     LibBcBlockchain *libbc_new_blockchain();
 
     // Its a good idea to prefix our C functions with something due to the lack of namespaces.
diff --git a/program/src/main.rs b/program/src/main.rs
index d0f25a4298805637d375a05d4bc1c09ae13b7780..59e72a57d533a072e4df79d701f2928388017b8a 100644
--- a/program/src/main.rs
+++ b/program/src/main.rs
@@ -1,7 +1,11 @@
+use blockchain_sys::libbc_blockchain_add;
+use blockchain_sys::libbc_new_blockchain;
 use blockchain_sys::LibBcBlockchain;
+use blockchain_sys::LibBcCallback;
 use blockchain_sys::LibBcPayload;
-use blockchain_sys::libbc_new_blockchain;
-use blockchain_sys::libbc_blockchain_add;
+use std::io::Write;
+use std::slice;
+use std::str;
 
 struct Blockchain {
     inner: *mut LibBcBlockchain,
@@ -10,7 +14,7 @@ struct Blockchain {
 impl Blockchain {
     pub fn new() -> Self {
         Self {
-            inner: unsafe { libbc_new_blockchain() }
+            inner: unsafe { libbc_new_blockchain() },
         }
     }
 
@@ -28,8 +32,6 @@ impl Blockchain {
     }
 }
 
-
-
 fn main() {
     let mut blockchain = Blockchain::new();
 
@@ -40,4 +42,44 @@ fn main() {
         blockchain_sys::libbc_blockchain_print(blockchain.inner);
         blockchain_sys::libbc_delete_blockchain(blockchain.inner);
     }
+
+    let mut sink = Sink::new();
+    let sink: *mut Sink = &mut sink;
+    let callback = LibBcCallback {
+        target: sink.cast(),
+        callback: Some(call_sink),
+    };
+
+    unsafe {
+        blockchain_sys::libbc_pass_callback(callback);
+    }
+}
+
+//Callback implementation
+
+struct Sink {
+    // this could be a channel that forwards data to the rest of the Rust program
+    channel: std::io::Sink,
+}
+
+impl Sink {
+    fn new() -> Self {
+        Self {
+            channel: std::io::sink(),
+        }
+    }
+}
+
+unsafe extern "C" fn call_sink(this: *mut std::ffi::c_void, payload: LibBcPayload) {
+    // Safety first. Does not happen, if we do everythign right.
+    let sink = match this.cast::<Sink>().as_mut() {
+        Some(s) => s,
+        None => return,
+    };
+
+    let slice = slice::from_raw_parts(payload.data, payload.len);
+
+    println!("Received message from C++: {:?}", str::from_utf8(slice));
+
+    let _ = sink.channel.write(slice);
 }