Extern "C", variadic template

Extern "C", variadic template
teofrast
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 140
0

2 pytania:
Question 1: Jak wywolac w ANSI C taki program w C++:

Kopiuj
#include <iostream>
#include <string>
#include <limits>

using std::string;
using std::cerr;

#define LOG_FUNC(x) cerr << '\n' << #x " = " << x << '\t'
#define LOG_ARG(x) cerr << #x " = " << x << '\t'

template <typename T>
class Money {
static_assert((std::numeric_limits<T>::is_integer || std::is_floating_point<T>::value) && "Number required.");
public:
   Money(const string & dollars, const long double cents);   
   Money(const string & dollars); 

   static Money create(const string & dollars, const long double cents);
   static Money create(const string & dollars);
};

template <typename T>
Money<T>::Money(const string & dollars, const long double cent) {
   LOG_FUNC(__func__);
   LOG_ARG(dollars);
   LOG_ARG(cent);
}

template <typename T>
Money<T>::Money(const string & dollars) {
   LOG_FUNC(__func__);
   LOG_ARG(dollars);
}

template <typename T>
Money<T> Money<T>::create(const string & dollars) {   
   LOG_FUNC(__func__);
   LOG_ARG(dollars);
   return Money<T>(dollars);
}

template <typename T>
Money<T> Money<T>::create(const string & dollars, const long double cents) {
   LOG_FUNC(__func__);
   LOG_ARG(dollars);
   LOG_ARG(cents);
   return Money<T>(dollars, cents);
}

template <typename T>
struct Creation {
	template<typename... Args>
	Money<T> operator()(Args...args) const {
		return Money<T>::create(std::forward<Args>(args)...);
	}
};

template <class Type, template<typename> class Template>
struct Constructor {
	template<typename... Args>
	Template<Type> operator()(Args...args) const {
		return Template<Type>(std::forward<Args>(args)...);
	}
};

template <typename Function, typename... Args> 
void call(Function && f, Args &&... args ) { 
   f(std::forward<Args>(args)...);
}

int main() {
   call(Constructor<int, Money>(), "-20.8", 5.0L);
   call(Constructor<long long, Money>(), "78");
   call(Creation<unsigned long long>(), "2", 5);
   call(Creation<long double>(), "7");
   cerr << '\n';
}

// g++ -Wfatal-errors -Wall -Wextra -Wconversion -std=c++14 

probowalem z extern "C" i void*, ale poza recznym przepisywaniem kazdej klasy szablonowej czyli: Money<int>, Money<long double="double">, ...,
wszystko co spelnia warunek: static_assert((std::numeric_limits<T>::is_integer || std::is_floating_point<T>::value) && "Number required.");
to nie mam pomyslu.
Question 2: A i czy ten program w samym C++ (bez odwolywania do C) to tez mozna jakos lepiej napisac bo nie wydaje mi sie abym wyczerpal najlepsze mozliwosci

enedil
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1029
4

W jakim sensie, "wywołać z C program"? Jakiś przykład użycia można prosić?

nalik
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1039
2
teofrast napisał(a):

np. bezposrednio z funkcji int main(void) w pliku main.c

Daj konkretny przykład użycia i opisz co chcesz osiągnąć.

TomaszLiMoon
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 530
1

A i czy ten program w samym C++ (bez odwolywania do C) to tez mozna jakos lepiej napisac bo nie wydaje mi sie abym wyczerpal najlepsze mozliwosci

IMO najprostsze rozwiązania są zawsze najlepsze. Zobacz jak można to odchudzić.

Kopiuj
#include <iostream>

enum class show { dollars , cents };

struct Tag
{
    Tag( std::ostream& out_ , show type_ ): out{out_} , type{type_} {}
    std::ostream& out;
    show type;    
}; 

auto operator<<( std::ostream& out , show type ){ return Tag{out,type}; }

std::ostream& operator<<( Tag tag , long double value )
{   
    if( tag.type == show::dollars ) tag.out << static_cast<long double>(value/100.0) << " dollars";
    else tag.out << value << " cents";
    return tag.out;
}

constexpr long double operator"" _dollars ( long double value ){ return value*100; }
constexpr long double operator"" _cents ( unsigned long long n ){ return n; }

int main() 
{   
   std::cout << show::dollars << -20.8_dollars+5_cents << std::endl;
   std::cout << show::cents << 2.1_dollars+78_cents << std::endl;
   std::cout << show::cents << 2.1_dollars-1.78_dollars-5000_cents << std::endl;
}

https://godbolt.org/z/sdsnPc8hq

kq
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Szczecin
2

Jak chcesz używać kodu z C++ z kodu w C to musisz wystawić api zgodne z C, co oznacza zabawę handlami, ifdefami, externami itd. zastanów się czy na pewno tego chcesz.

teofrast
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 140
0

tak, wlasnie chce sie tego nauczyc i pisze program testowy

EL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 143
0

Nie zapomnij o wyjatkach. W praktyce prawie kazda funkcje trzeba bedzie opakowac w try. No i do C zwrocic kod bledu. A moze i tekst bledu. A jesli tak to moze i rozmiar bufora jesli to klient ma przydzielac pamiec.

several
  • Rejestracja: dni
  • Ostatnio: dni
2
teofrast napisał(a):

tak, wlasnie chce sie tego nauczyc i pisze program testowy

W takim razie wystawiasz interfejs w postaci nagłówka zgodnego z C, który otaczasz takim czymś

Kopiuj
#ifdef __cplusplus
extern "C" {
#endif

// twoje funkcje


#ifdef __cplusplus
}
#endif

Wtedy jak skompilujesz kod C++ do binarnej biblioteki, możesz ją używać w C poprzez ten właśnie nagłówek. Nie zapomnij oczywiście o strażniku nagłówka. Implementacje tychże funkcji w pliku .cpp mogą już zawierać C++.

teofrast
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 140
0

Na razie tylko czesc zrobilem i dokoncze potem (nie ma np. obslugi wyjatkow, obslugi szablonow - tylko na sztywno dla 1 Money<int> jest, a takze recznego wczytywania bibliotek wspoldzielonych przez dlopen) ale to co jest testowalem i chyba dziala:
https://github.com/carneades3/Linking

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2646
1

W sensie chcesz używać funkcjonalności napisanych w języku c++ czy chcesz odpalić plik wykonywalny?
Jeżeli plik wykonywalny to coś takiego:

Kopiuj
#include <stdlib.h>
...
int status = system("./foo 1 2 3");

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.