Created
January 28, 2016 20:47
-
-
Save aprell/f5a713c698058f537aae to your computer and use it in GitHub Desktop.
Calling C++ from C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <assert.h> | |
| typedef struct Int_array Int_array; | |
| extern Int_array *array_new(size_t); | |
| extern Int_array *array_copy(Int_array *); | |
| extern Int_array *array_move(Int_array *); | |
| extern void array_delete(Int_array *); | |
| extern size_t array_length(Int_array *); | |
| extern int array_at(Int_array *, size_t); | |
| extern int array_set(Int_array *, size_t, int); | |
| int main(void) | |
| { | |
| Int_array *a = array_new(3); | |
| assert(array_length(a) == 3); | |
| size_t i; | |
| for (i = 0; i < array_length(a); i++) { | |
| array_set(a, i, i+1); | |
| printf("a[%zu] = %d\n", i, array_at(a, i)); | |
| } | |
| Int_array *b = array_copy(a); | |
| assert(array_length(b) == 3); | |
| assert(array_length(a) == 3); | |
| array_delete(a); | |
| for (i = 0; i < array_length(b); i++) { | |
| printf("b[%zu] = %d\n", i, array_at(b, i)); | |
| } | |
| Int_array *c = array_move(b); | |
| assert(array_length(c) == 3); | |
| assert(array_length(b) == 0); | |
| array_delete(b); | |
| for (i = 0; i < array_length(c); i++) { | |
| printf("c[%zu] = %d\n", i, array_at(c, i)); | |
| } | |
| array_set(c, 3, 42); // throws exception | |
| array_delete(c); | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| template<typename T> | |
| struct T_array { | |
| T *elems; | |
| size_t num_elems; | |
| T_array() : elems(nullptr), num_elems(0) {} | |
| T_array(size_t n) : elems(new T[n]), num_elems(n) {} | |
| T_array(const T_array &rhs) | |
| : elems(new T[rhs.num_elems]), num_elems(rhs.num_elems) | |
| { | |
| memcpy(elems, rhs.elems, num_elems * sizeof(T)); | |
| } | |
| T_array(T_array &&rhs) | |
| : elems(rhs.elems), num_elems(rhs.num_elems) | |
| { | |
| rhs.elems = nullptr; | |
| rhs.num_elems = 0; | |
| } | |
| ~T_array() { delete[] elems; } | |
| T &operator[](size_t i) { return elems[check(i)]; } | |
| size_t check(size_t i) | |
| { | |
| if (i >= num_elems) { | |
| std::cerr << "Index " << i << " is out of range [0," << num_elems << ")\n"; | |
| throw std::out_of_range {"T_array::check"}; | |
| } | |
| return i; | |
| } | |
| }; | |
| extern "C" { // C linkage | |
| using Int_array = T_array<int>; | |
| Int_array *array_new(size_t n) | |
| { | |
| return new Int_array(n); | |
| } | |
| Int_array *array_copy(Int_array *a) | |
| { | |
| return new Int_array(*a); | |
| } | |
| Int_array *array_move(Int_array *a) | |
| { | |
| return new Int_array(std::move(*a)); | |
| } | |
| void array_delete(Int_array *a) | |
| { | |
| delete a; | |
| } | |
| size_t array_length(Int_array *a) | |
| { | |
| return a->num_elems; | |
| } | |
| int array_at(Int_array *a, size_t i) | |
| { | |
| return (*a)[i]; | |
| } | |
| void array_set(Int_array *a, size_t i, int v) | |
| { | |
| (*a)[i] = v; | |
| } | |
| } // extern "C" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| CC = clang | |
| CFLAGS = -Wall -Wextra | |
| CXX = clang++ | |
| CXXFLAGS = $(CFLAGS) -std=c++11 | |
| extern: extern.o extern_C.o | |
| $(CXX) $(CXXFLAGS) $^ -o $@ | |
| clean: | |
| rm -f extern extern.o extern_C.o | |
| .PHONY: clean |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment