Skip to content

Instantly share code, notes, and snippets.

@aprell
Created January 28, 2016 20:47
Show Gist options
  • Select an option

  • Save aprell/f5a713c698058f537aae to your computer and use it in GitHub Desktop.

Select an option

Save aprell/f5a713c698058f537aae to your computer and use it in GitHub Desktop.
Calling C++ from C
#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;
}
#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"
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