Wrapper function for template<> in C++ - c++

I am currently trying to create a wrapper interface that can translate C++ to C, and while studying on the possibilities to do that, I came across the template functions (and classes). Knowing that these functions can take any data type and return any data type as well, I find it hard to create a corresponding caller function name that C could read. A simple example is the adder.
template <class typesToAdd>
typesToAdd addStuff(typesToAdd a, typesToAdd b) {
return a + b;
}
My interface includes the extern "C" command to avoid the C++ name mangling in C.

Template is not a function that works for any data type. It is a template for a function that is created at compilation time. Each type you use creates a new function with a new symbol in the binary.
To export to C, you will have to specialize the type you want to use from C, like:
template <class typesToAdd>
typesToAdd addStuff(typesToAdd a, typesToAdd b) {
return a + b;
}
extern "C" {
int addStuffInt(int a, int b) {
return addStuff(a, b);
}
}

You may use function templates to simplify both implementing and maintaining the actual code that does the work but to provide a C interface, you'll still need to explicitly instantiate the functions for the types you aim to support.
If you'd like a C++ user to have the same restricted access to the functions as a C user will have, you can move the template implementation into the .cpp file and do the explicit instantiation there. A C++ user trying to use the function with types for which you have not explicitly instantiated the template will get a linking error.
It could look something like this:
// a.hpp
#pragma once
template <class T>
T addStuff(const T& a, const T& b); // no implementation here.
// a.cpp
#include "a.hpp"
#include "a.h"
template <class T>
T addStuff(const T& a, const T& b) {
T rv = a;
rv += b;
return rv;
}
// C interface - note: it's inside the .cpp file
extern "C" {
int add_ints(int a, int b) {
return addStuff(a, b);
}
double add_doubles(double a, double b) {
return addStuff(a, b);
}
}
/* a.h */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int add_ints(int, int);
double add_doubles(double, double);
#ifdef __cplusplus
}
#endif
A C user can now include the .h file and call the two functions for which you've provided an implementation.
Example:
// main.c
#include "a.h"
#include <stdio.h>
int main() {
printf("%d\n", add_ints(10, 20));
printf("%f\n", add_doubles(3., .14159));
}
Compilation:
g++ -c a.cpp
gcc -o main main.c a.o

Related

Call function outside of current namespace in C++

I'm trying to call a function defined in a C file from my CPP code and I think I am having issues getting the correct namespace. When compiling I get the error: "Undefined reference to 'Get'".
My C header:
// c.h
#ifndef C_H
#define C_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum
{
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum
{
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct
{
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d);
#ifdef __cplusplus
}
#endif
#endif
And my CPP file:
// main.cpp
...
extern "C" {
#include "c.h"
}
...
namespace MyNamespace
{
...
MyClass::MyFunc()
{
TYPE_D d;
// None of these calls will compile
// Get(VAL_B1, &d);
// ::Get(VAL_B1, &d);
}
...
}
I have tried calling without namespace reference and also with the "root" namespace using "::" with no luck. Any help is appreciated. I've read through this which seems to clarify it but I don't really understand it:
using C++ with namespace in C
"Undefined reference" means that the function has been declared (in the header), but not defined. You'll need to define the function in a source file somewhere (presumably the C file you refer to), and make sure that is linked when you build the program.
First, let's note what that error means. An undefined reference at the linker stage means that the compiler is unable to find the instance of something. In this case, the implementation of a function.
Let's look at your code.. There are a few things missing that we need to add to make it compilable:
A definition for Get().
main()
The class definition for MyClass.
Once we added those three fixes, the code compiles without error.
extern "C" { extern "C" {
typedef enum {
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum {
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum {
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct {
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d) {
return VAL_A1;
}
}}
namespace MyNamespace {
struct MyClass {
void MyFunc();
};
void MyClass::MyFunc() {
TYPE_D d;
Get(VAL_B1, &d);
::Get(VAL_B1, &d);
}
}
int main() {}
The definition of Get (not shown in the question) also needs to be enclosed in extern "C".
The main difference between C and C++ functions, in practice, is the way they are named in the executable format. C++ functions get "name mangling" treatment by the linker but C functions do not. The linker will see the C++ definition of Get and it will have no idea of its relation to the C declaration, even if they have the same signature.

C++ class template undefined reference to function [duplicate]

This question already has answers here:
undefined reference to template function [duplicate]
(2 answers)
Closed 6 years ago.
I keep getting undefined reference when i call the two functions from my template class "add" and "greater" in my main function.
So, i have:
number.h
#ifndef NUMBER_H
#define NUMBER_H
template <class T>
class number {
public:
T x;
T y;
number (int a, int b){
x=a; y=b;}
int add (T&);
T greater ();
};
#endif
number.cpp
#include "number.h"
template <class T>
int number<T>::add (T& rezAdd){
rezAdd = x+y;
return 1;
}
template <class T>
T number<T>::greater (){
return x>y? x : y;
}
And my main file is: resolver.cpp
#include <stdio.h>
#include <stdlib.h>
#include "number.h"
int main (int argc, char **argv) {
int aux;
number<int> c(3,5);
c.add(aux);
printf ("number added [%d]\n", c.add(aux));
printf ("greater number: [%d]\n", c.greater());
return 0;
}
The errors that i keep getting are:
g++ -Wall -o tema1 resolver.cpp number.cpp
/tmp/ccX483J4.o: In function `main':
resolver.cpp:(.text+0x34): undefined reference to `number<int>::add(int&)'
resolver.cpp:(.text+0x47): undefined reference to `number<int>::add(int&)'
resolver.cpp:(.text+0x64): undefined reference to `number<int>::greater()'
collect2: ld returned 1 exit status
make: *** [all] Error 1
Thanks for the help in advance!
I prefer to have all of my functions in the .cpp file, regardless of whether they are template functions or regular functions. And there is a way to do that with some basic #ifndef magic. Here's what you can do:
main.cpp
#include "myclass.hpp"
int main()
{
// ...
}
myclass.hpp
#ifndef MYCLASS
#define MYCLASS
template<class T>
class MyClass
{
T val;
public:
MyClass(T val_);
}
#define MYCLASS_FUNCTIONS
#include "myclass.cpp"
#endif
myclass.cpp
#ifndef MYCLASS_FUNCTIONS
#include "myclass.hpp"
// regular functions:
// ...
#else
// template functions:
template<class T>
MyClass<T>::MyClass(T val_)
:val(val_)
{}
// ...
#endif
Here's how the precompiler sees it. We have two .cpp files.
When we compile main.cpp we:
include myclass.hpp
check that MYCLASS is undefined, and it is
define it
give compiler the definitions of the generated class (from template class)
include myclass.cpp
define MYCLASS_FUNCTIONS
check if MYCLASS_FUNCTIONS is defined, it is
give compiler the definitions of the generated functions (from template functions)
When we compile myclass.cpp
check if MYCLASS_FUNCTIONS is defined, it isn't
include myclass.hpp
check that MYCLASS is undefined, and it is
define it
give compiler the definitions of the class
include myclass.cpp
include myclass.hpp again
this time MYCLASS is defined so do nothing inside, return to myclass.cpp
check if MYCLASS_FUNCTIONS is defined, it is
give compiler the definition of the generated functions (from template functions)
exit include twice
pass to the compiler all the regular functions
Your class is named wrong. Your class is named cai where all your functions belong to a class named number: http://ideone.com/ZayX0c
One more thing.. you cannot have templates in the .cpp file. Template functions/defintions go in the header along with the class declaration. This is the reason for your undefined function error. Non-template functions go in the .cpp.
#include <cstdio>
#include <cstdlib>
template <class T>
class number {
public:
T x;
T y;
number (int a, int b){
x=a; y=b;}
int add (T&);
T greater ();
};
template <class T>
int number<T>::add (T& rezAdd){
rezAdd = x+y;
return 1;
}
template <class T>
T number<T>::greater (){
return x>y? x : y;
}
int main (int argc, char **argv) {
int aux;
number<int> c(3,5);
c.add(aux);
printf ("number added [%d]\n", c.add(aux));
printf ("greater number: [%d]\n", c.greater());
return 0;
}
Move the definitions of the add and greater function templates into your number.h.
Remember that add and greater aren't functions, they're function templates. To create actual functions, the compiler has to instantiate the template for specific types, such as int, and it can only do that if it has access to the template's definition at the point where it discovers that an instance is needed.
When you compile number.cpp, the compiler has access to the templates' definitions, but it doesn't see any code that requires a specific instance (such as number<int>), so it doesn't generate instances.
When you compile resolver.cpp, the compiler sees that it needs to instantiate those templates for the int type, but it can't since it doesn't have their definitions. So it generates "external references", basically notes telling the linker to look for those functions in some other object file.
The result is that the function templates don't get instantiated in either object file — in one because the compiler didn't know that it should, and in the other because it couldn't — so when the linker goes looking for them (to resolve those external references), it can't find them. That's why you get the error.
Moving the template function definitions into the header makes them visible to the compiler while it's compiling main.cpp, so it's able to instantiate those functions for the int type. Function templates typically need to be defined in header files, rather than .cpp files, for exactly this reason.

using a template function as dll in another project

I have a simple function like this:
cusp.dll
#define EXPORT extern "C" __declspec (dllexport)
EXPORT
void cuspDsolver(int *r, int *c, double *v, double *x, double *b, int size, int nnz,double tol)
{
.
.
.
.
.
}
and I created a dll using these two lines:
#define EXPORT extern "C" __declspec (dllexport)
EXPORT
and I called this function in other Project using this method:
HINSTANCE hDLL = LoadLibrary("C:\\Users\\Administrator\\Documents\\Visual Studio 2012\\Projects\\Ardalan_12\\cusp.dll");
if(hDLL == NULL)
{
cout<< "Failed to load DLL" <<endl;
}
typedef void(*fnPtr)(int *, int *, double *, double *, double *, int , int ,double);
fnPtr pfn;
pfn=(fnPtr)GetProcAddress(hDLL,"cuspDsolver");
if(pfn)
{
pfn(rowOffset,colIndex,values,answer,rightHandSide,theSize,nnz,0.9);
}
FreeLibrary(hDLL);
this works very fine, but now I changed my function to this
//#define EXPORT extern "C" __declspec (dllexport)
//EXPORT
template <typename LinearOperator,typename Vector>
void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol)
{
cusp::default_monitor<double> monitor(B, 10000, tol);
cusp::precond::scaled_bridson_ainv<double,cusp::device_memory> PRE(A);
DWORD dw1 = GetTickCount();
cusp::krylov::cg(A,X,B,monitor,PRE);
DWORD dw2 = GetTickCount();
double dw3 = dw2 - dw1;
cout <<endl << "time spent is : " << dw3 << endl;
cout << endl << "developed by cusp!!!" << endl;
}
but Visual Studio won't allow extern "C" __declspec (dllexport) with template functions is there any way to do this easily?actually I'm not expert,so would you please explain this to me in detail?
There is no such thing as a "template function." There is a function template, however; that is a template from which functions are created by instantiation. In this case, the distinction is important.
To call a function instantiated from a template, you must have access to that instantiation. The most common case is to implement the template in a header file and simply #include it (see this SO question for more details). I believe that you want your function to be usable with arbitrary client-supplied types as LinearOperation and Vector, so a header-only implementation is your only option.
If, on the other hand, you know all the types you would want to instantiate the template with when building your library, you can actually explicitly instantiate the template for those types and export these explicit instantiations. Like this:
Header file
template <typename LinearOperator,typename Vector>
void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol);
Source file
template <typename LinearOperator,typename Vector>
void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol)
{
// body here
}
template __declspec(dllexport) void cuspDsolver(MyConcreteOperator1& A, MyConcreteVector1& X, MyConcreteVector1& B, double tol);
template __declspec(dllexport) void cuspDsolver(MyConcreteOperator2& A, MyConcreteVector2& X, MyConcreteVector2& B, double tol);
// etc.
Such instantiations cannot be extern "C", however (they all have the same function name, after all). So if you want to load them dynamically, you'll have to provide uniquely-named C-linkage accessors to them.
Still, I believe what you're really looking for is implementing the funciton in a header file.
Based on your comments, here is how you could actually make your library dynamically loadable while using CUSP internally.
You cannot have a function template in your library's public interface. So let's say you want to allow using your library with the following types of LinearOperator: OperatorCharm and OperatorTop, and with the following types of Vector: FancyVector<float> and FancyVector<double>. Then, your public interface could look like this:
template <typename LinearOperator,typename Vector>
void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol)
{
// body
}
EXPORT void cuspDsolver_Charm_float(params_which, correspond_to, OperatorCharm_and, FancyVector_of_float)
{
cuspDsolver(params);
}
EXPORT void cuspDsolver_Charm_double(params_which, correspond_to, OperatorCharm_and, FancyVector_of_double)
{
cuspDsolver(params);
}
EXPORT void cuspDsolver_Top_float(params_which, correspond_to, OperatorTop_and, FancyVector_of_float)
{
cuspDsolver(params);
}
EXPORT void cuspDsolver_Charm_double(params_which, correspond_to, OperatorTop_and, FancyVector_of_double)
{
cuspDsolver(params);
}
You don't even have to instantiate the template explicitly any more, since it will be instantiated implicitly for the calls in the EXPORT-ed functions.
So in effect, your public API will be those 4 cuspDsolver_a_b functions, which can be queried dynamically as normal.
Template functions are not compiled and thus not part of a DLL as there's an infinite number of function derived from a template.
Only specific instances of the template are compiled and linked into a binary. You can expose those specialized template functions in a DLL. You'll need a header file for those names as string them in a hardcoded string is problematic.
If you want to use a template function w/o specializing it, export it through a header file.

Accessing C++ templates from C

I am using OpenCV for some image manipulation and it has several functions that must be given a data type to perform correctly. My idea is to template these functions so I do not have to write a separate function for each possible data type it could be.
However, the code I would like the code I am writing to be compatible with some existing C code I have that stores images in memory so I can pass it around easier without writing the image to disc constantly.
The problem I am running into is how to make my .h files and libraries to let the C program call the C++ template functions. I have not had a chance to try it yet, but so far what I have would look something what follows:
foo.h
int foo(int a, int, b);
float foo(float a, float b);
foo.c:
int foo(int a, int b) {
return footemp(a, b);
}
float foo(float a, float b) {
return footemp(a, b);
}
foo.hpp:
template<class t>
t footemp(t a, t b) {
return a + b;
}
Which does not work since it requires my .c file to know about a templated file.
So I am open to suggestions. Thank you in advance for the help
This is possible, with some care. Use a C++ source file foo.cpp:
#include "foo.h"
#include "footemp.hpp"
int foo_int(int a, int b) {
return footemp(a, b);
}
float foo_float(float a, float b) {
return footemp(a, b);
}
In foo.h, use extern "C" to make C-compatible declarations, with an #ifdef to allow use as either C or C++:
#ifdef __cplusplus
extern "C" {
#endif
int foo_int(int a, int, b);
float foo_float(float a, float b);
#ifdef __cplusplus
}
#endif
Compile this as a C++ library—static or dynamic, it doesn’t matter. In your C sources you can now #include "foo.h" and use these functions as you would expect, so long as you link against the library.
I imagine one thing you could do is write the function in C++, declaring the specializations you want, and at the same time defining extern "C" functions that forward the calls to the template functions.
Keep in mind if you're using C for the other stuff, you're going to need to name the functions different; C doesn't do function overloading.
As mday299 mentioned, there is no templates in C.
However, if your C code is contained in a saparate compilation unit (.exe/.dll), you can provide C interface for your template functions almost like you did it:
foo.h
/* C interface */
int fooInt(int a, int, b);
float fooFloat(float a, float b);
foo.hpp
template <class T> foo(T a,T b)
{
return a+b;
}
foo.cpp:
#include "foo.h"
#include "foo.hpp"
int fooInt(int a, int b) {
return foo<int>(a, b);
}
float fooFloat(float a, float b) {
return foo<float>(a, b);
}
Then, project would be compiled separate using c++, and c part would see only foo.h and lib/dll file
No templates in C. That's a C++ feature. Sorry.
There is a good chance that you'll be able to compile your C file with a C++ compiler. So you can build your whole project, both C and C++ sources with a C++ compiler.
You are already compiling it with a C++ compiler, otherwise you wouldn't be able to compile your overloaded foo functions.

Can I use shared library created in C++ in a C program?

I am creating programs using C. However, I require to use a lot of libraries that have API's only for C++. So, is it possible that I can create a shared object in C++ and then access its functionality using C?
The only data I would be passing and returning would be C compatible data types.
Converting or migrating to cpp is not an option here.
If it is not possible to interface these codes, how do I get information from C++ code to C code?
I tried calling C++ functions from C, but I get errors during linking when I include <string>. So when I call C++ functions from C, should I only use that code which will be C compiler compatible?
C++ header cppfile.hpp
#ifndef CPPFILE_H
#define CPPFILE_H
#ifdef __cplusplus
extern "C" {
#endif
extern int myfunction(const char *filename);
#ifdef __cplusplus
}
#endif
#endif
C++ file cppfile.cpp
#include "cppfile.hpp"
#include <string>
int myfunction(const char *filename) {
String S(filename);
return 0;
}
C file cmain.c
#include "cppfile.hpp"
int main(int argc, char **argv)
{
int i = myfunction(argv[1]);
printf("%d\n", i);
return 0;
}
Compiling:
gcc -c cmain.c
g++ -fPIC -shared -o cppfile.so cppfile.cpp
You want something more like this (and here I will use a slightly more meaningful example):
C/C++ header - animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#ifdef __cplusplus
class Animal {
public:
Animal() : age(0), height(0) {}
Animal(int age, float height) : age(age), height(height) {}
virtual ~Animal() {}
int getAge();
void setAge(int new_age);
float getHeight();
void setHeight(float new_height);
private:
int age;
float height; // in metres!
};
#endif /* __cplusplus */
#ifdef __cplusplus
extern "C" {
#endif
struct animal; // a nice opaque type
struct animal *animal_create();
struct animal *animal_create_init(int age, float height);
void animal_destroy(struct animal *a);
void animal_setage(struct animal *a, int new_age);
void animal_setheight(struct animal *a, float new_height);
int animal_getage(struct animal *a);
float animal_getheight(struct animal *a);
#ifdef __cplusplus
}
#endif
#endif /* ANIMAL_H */
C++ animal implementation file - animal.cpp
#include "animal.h"
#define TO_CPP(a) (reinterpret_cast<Animal*>(a))
#define TO_C(a) (reinterpret_cast<animal*>(a))
void Animal::setAge(int new_age) { this->age = new_age; }
int Animal::getAge() { return this->age; }
void Animal::setHeight(float new_height) { this->height = new_height; }
float Animal::getHeight() { return this->height; }
animal *animal_create() {
animal *a = TO_C(new Animal);
return a;
}
animal *animal_create_init(int age, float height) {
animal *a = TO_C(new Animal(age, height));
return a;
}
void animal_destroy(animal *a) {
delete TO_CPP(a);
}
void animal_setage(animal *a, int new_age) {
TO_CPP(a)->setAge(new_age);
}
void animal_setheight(animal *a, float new_height) {
TO_CPP(a)->setHeight(new_height);
}
int animal_getage(animal *a) {
TO_CPP(a)->getAge();
}
float animal_getheight(animal *a) {
TO_CPP(a)->getHeight();
}
C client code - main.c
#include "animal.h"
#include <stdio.h>
int main()
{
// 6'0" 25yo (perhaps a human? :P)
struct animal *a = animal_create(25, 1.83);
animal_setage(a, 26); // birthday
printf("Age: %d\nHeight: %f", animal_getage(a), animal_getheight(a));
animal_destroy(a);
return 0;
}
C++ client code - main.cpp
#include "animal.h"
#include <iostream>
int main()
{
// 6'0" 25yo (perhaps a human? :P)
Animal* a = new Animal(25, 1.83);
a->setAge(26); // birthday
std::cout << "Age: " << a->getAge() << std::endl;
std::cout << "Height: " << a->getHeight();
delete a;
return 0;
}
So when you compile the library, you compile animal.cpp with a C++ compiler. You can then link to it with C code, and use the animal_xxx functions.
Note the use of struct animal and Animal. Animal is a normal C++ type. It's exactly what it looks like. struct animal, on the other hand, is an "opaque" type. That means that your C program can see it's there, and can have one, but it doesn't know what is inside it. All it knows is that it has a function that takes a struct animal*.
In a real library you will want to have customisation points for memory allocation. So assuming this is the library libjungle, you probably want at least jungle_setmalloc and jungle_setfree with sensible defaults. You can then set up the global new and delete in libjungle's C++ code to use these user-defined functions.
This is entirely possible. Here is how, quickly:
1.) You have a header.h with a C API that doesn't include any Cplusiness.
#ifndef MIXEDCCPP_H
#define MIXEDCCPP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> // Any C-compatible headers will go here.
// C API goes here. C Functions can't contain any CPPiness.
void myclass_setName( void *pClassObj, const char *pName, int nameLen );
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
// Stuff that is only compatible with CPP goes here
// __cplusplus section won't get processed while compiling C files.
#include <vector> // CPP headers.
class MyClass {
// Classes etc.
};
#endif // #ifdef __cplusplus
#endif // MIXEDCCPP_H
Then in the .cpp, you simply create some C-API functions that can even include CPP right in them:
#include "mixedccpp.h"
extern "C" {
// C API goes here. C Functions can't contain any CPPiness in their prototypes.
void myclass_setName( void *pClassObj, const char *pName, int nameLen )
{
// But CPP knowledge can go inside the function - no problem, since this is a CPP file.
MyClass *pMyClass = static_cast<MyClass *>(pClassObj);
pMyClass->setName( pName, nameLen );
}
} // #extern "C"
// CPP Stuff goes here... or vice-versa.
In your case, you don't actually need any CPP code declared in your header since you are calling external libraries. But you need to create C-compatible functions in your CPP file which can call out to CPP libraries. Use extern "C" for those functions that need to be called from C files, and then use C-structs instead of classes and, if classes are needed, use void * to point to them and then cast them back to their class from the C function any time you need to access them. A standard makefile should be able to compile this just fine, assuming it compiles .cpp files as .cpp and understands extern "C" {}
Your C code cannot use the C++ header <string>. You have to ensure that the functions in the C++ API that are to be called from C are declared extern "C" (as you have), and use only types recognized by a C compiler (as you have).
You also need to link with the C++ compiler if any of your code is in C++. You can do it otherwise if you're prepared to spend a lot of energy getting the loader options right, but it is far simpler just to use the C++ compiler:
gcc -c cmain.c
g++ -fPIC -shared -o cppfile.so cppfile.cpp
g++ -o cmain cmain.o cppfile.so
Of course, you need to:
Add #include <stdio.h> in cmain.c.
Use std::string S(filename); in cppfile.cpp.
Also, if the program is invoked without arguments, you get:
$ ./cmain
terminate called throwing an exceptionAbort trap: 6
$ ./cmain x3
0
$
You need to protect against misuse, even in test programs.