Skip to content

Instantly share code, notes, and snippets.

@caiorss
Created May 24, 2019 03:58
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save caiorss/c236aedbbb514717ad26e856654bb063 to your computer and use it in GitHub Desktop.
Save caiorss/c236aedbbb514717ad26e856654bb063 to your computer and use it in GitHub Desktop.
Example - Calling C++ from C
cmake_minimum_required(VERSION 3.9)
project( CallCppFromC)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_executable(main main.c codecpp.cpp codecpp.hpp)
#include "codecpp.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
//----------- Implementation of class RunningStatics -----------//
Runstat::Runstat()
{
std::cout << " [TRACE] Object created Ok." << std::endl;
m_sum = 0.0;
m_sumsq = 0.0;
m_N = 0;
}
Runstat::~Runstat()
{
std::cout << " [TRACE] Object deleted OK" << std::endl;
}
void
Runstat::add(double x)
{
m_sum += x;
m_sumsq += x * x;
m_N++;
}
size_t
Runstat::size() const
{
return m_N;
}
void
Runstat::reset()
{
m_sum = 0.0;
m_sumsq = 0.0;
m_N = 0;
}
double
Runstat::mean() const
{
return m_sum / m_N;
}
double
Runstat::sdev() const
{
size_t N = m_N;
return std::sqrt((m_sumsq - m_sum * m_sum / N) / (N - 1.0));
}
//--------- C-Interface for class std::string ------------------//
hString string_new()
{
return new std::string{};
}
hString string_new1(const char* text)
{
return new std::string(text);
}
// Copy constructor
hString string_copy(hString self)
{
std::string* p = reinterpret_cast<std::string*>(self);
return new std::string(*p);
}
void string_del(hString self)
{
delete reinterpret_cast<std::string*>(self);
}
void string_add(hString self, const char* text)
{
auto p = reinterpret_cast<std::string*>(self);
*p = *p + text;
}
void string_disp(hString self, const char* name)
{
auto p = reinterpret_cast<std::string*>(self);
std::cout << name << " / std::string{ " << *p << "} " << std::endl;
}
//---------- C-Interface for class Runstat ---------------------//
pStat Runstat_new()
{
return new (std::nothrow) Runstat();
}
void Runstat_del(pStat self)
{
delete reinterpret_cast<Runstat*>(self);
}
void Runstat_add(pStat self, double x)
{
auto p = reinterpret_cast<Runstat*>(self);
p->add(x);
}
double Runstat_mean(pStat self)
{
Runstat* p = reinterpret_cast<Runstat*>(self);
return p->mean();
}
double Runstat_sdev(pStat self)
{
Runstat* p = reinterpret_cast<Runstat*>(self);
return p->sdev();
}
size_t Runstat_size(pStat self)
{
Runstat* p = reinterpret_cast<Runstat*>(self);
return p->size();
}
#ifndef _CODECPP_
#define _CODECPP_
#ifdef __cplusplus
#define EXPORT_C extern "C"
#else
#define EXPORT_C
#endif
//============ C++ Only Header =================//
#ifdef __cplusplus
#include <iostream>
class Runstat
{
/// Sum of sequence processed
double m_sum;
/// Sum of squares processed
double m_sumsq;
/// Size of sequence processed
size_t m_N;
public:
Runstat();
Runstat(Runstat const&) = delete;
Runstat& operator=(Runstat const&) = delete;
~Runstat();
void add(double x);
void reset();
size_t size() const;
double mean() const;
/// Standard deviation
double sdev() const;
};
#endif //-- End of __cplusplus definition //
// ========== C-interface for std::string container
typedef void* hString;
EXPORT_C hString string_new();
EXPORT_C hString string_new1 (const char* text);
EXPORT_C hString string_copy (hString self);
EXPORT_C void string_del (hString self);
EXPORT_C void string_add (hString self, const char* text);
EXPORT_C void string_disp (hString, const char* name);
//============ C-interface for class Runstat ============//
// Opaque pointer type alias for C-lang
typedef void* pStat;
EXPORT_C pStat Runstat_new();
EXPORT_C void Runstat_del (pStat self);
EXPORT_C void Runstat_add (pStat self, double x);
EXPORT_C double Runstat_mean(pStat self);
EXPORT_C double Runstat_sdev(pStat self);
EXPORT_C size_t Runstat_size(pStat self);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "codecpp.hpp"
int main()
{
printf("\n == EXPERIMENT 1 - std::string C-wrapper ======\n");
hString str = string_new1("A C++ string in C");
string_disp(str, "str");
hString str2 = string_copy(str);
string_add(str, " - hello world");
string_disp(str, "str");
string_disp(str2, "str2");
string_del(str);
string_del(str2);
printf("\n == EXPERIMENT 2 - Class Runstat ======\n");
pStat obj = Runstat_new();
Runstat_add(obj, 10.0);
Runstat_add(obj, 4.0);
Runstat_add(obj, 25.0);
Runstat_add(obj, 16.0);
printf(" Number of Elements processed = %zu \n", Runstat_size(obj));
printf(" Mean = %.5f \n", Runstat_mean(obj));
printf(" Sdev = %.5f \n", Runstat_sdev(obj));
Runstat_add(obj, -50.0);
Runstat_add(obj, 80.0);
printf(" Mean = %.5f \n", Runstat_mean(obj));
printf(" Sdev = %.5f \n", Runstat_sdev(obj));
// Delete C++ Object
Runstat_del(obj);
return 0;
}
$ ./main.bin
== EXPERIMENT 1 - std::string C-wrapper ======
str / std::string{ A C++ string in C}
str / std::string{ A C++ string in C - hello world}
str2 / std::string{ A C++ string in C}
== EXPERIMENT 2 - Class Runstat ======
[TRACE] Object created Ok.
Number of Elements processed = 4
Mean = 13.75000
Sdev = 8.95824
Mean = 14.16667
Sdev = 41.69612
[TRACE] Object deleted OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment