c++ call fmt Libary from C Code with va_args - c++

I'd like to use the fmt libary as part of a debugging framework.
However our project is mixed c and c++.
fmt works nice with c++ however in c we have printf() like format strings.
//c readable header
#ifdef __cplusplus
extern "C"
{
#endif
void Foo(char* format, ...);
#ifdef __cplusplus
}
#endif
//impl.cpp
void Foo(char* format, ...)
{
va_list aptr;
va_start(aptr, format);
//pass aptr to fmt lib somehow
va_end(aptr);
}
Therefore I have to "hide" the C++ part from C code.
The only way (I know) in c how to do formatting is using va_args. However they will not work with fmt templates since the first one is executed at run time and the other one at compile time
=>So the Question
Do you have an idea how to use the fmt lib from C Code?
Thx for your Input :)

You can call formatting functions from C via a wrapper that uses dynamic_format_arg_store to construct argument lists at runtime. However, for that to work you'll need to know all argument types so it won't work with varargs which don't preserve the type information.

Related

How do I call C++ functions from C?

I'm writing a C program (myapp) which needs to use a particular api; the api is written in C++. I've worked with C and C++, but never both at once, and I'm getting confused.
So, the api provides the following directory, which I've placed in a folder called include, at the same level as my makefile:
libmyapi.a
api/api.h
My main source file is src/myapp.c, and it includes the api using #include "api/api.h".
My make command is (plus some flags, which I haven't listed because I don't think they're relevant here):
gcc -Linclude -lmyapi -Iinclude src/myapp.c -o lib/myapp.sp -lrt
The problem I'm having is that the api.h file contains references to namespaces etc. Eg at one point it has:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
and obviously the C compiler doesn't know what this means.
So, I assumed I'd need to compile using a C++ compiler, but then someone said I didn't, and I could just "wrap" the code in "extern 'C'", but I don't really understand. Having read around online, I'm not any further on.
Do I need to compile in C++ (ie using g++)?
Do I need to "wrap" the code, and what does that mean? Do I just do
#ifdef __cplusplus
extern "C" {
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
}
#endif
or do I just wrap the lines
namespace MyAPI {
namespace API {
and then their corresponding }}?
The header file calls other header files, so potentially I'll need to do this in quite a lot of places.
So far I've got errors and warnings with all the variations I've tried, but I don't know whether I'm doing the wrapping wrong, setting g++ compiler flags wrong, using the wrong compiler, or what! If I know the method to use, I can at least start debugging. Thank you!
You can write a small C++ program that creates a C binding for the API.
Gvien this API:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
you can create c_api.h
#ifdef __cplusplus
extern "C" {
#endif
struct api_handle_t;
typedef struct api_handle_t* api_handle;
api_handle myapi_api_create();
void myapi_api_some_function_using_api(api_handle h);
void myapi_api_destroy(api_handle h);
#ifdef __cplusplus
}
#endif
and c_api.cpp
#include "c_api.h"
#include <myapi/api/stuff.hpp>
struct api_handle_t
{
MyAPI::API::SimpleConnection c;
};
api_handle myapi_api_create()
{
return new api_handle_t;
}
void myapi_api_some_function_using_api(api_handle h)
{
//implement using h
}
void myapi_api_destroy(api_handle h)
{
delete h;
}
compile that with a C++ compiler and include the c_api.h file in the C project and link to the library you created with the C++ compiler and the original library.
Basically, your C++ library needs to export a pure C API. That is, it must provide an interface that relies solely on typedef, struct, enum, preprocessor directives/macros (and maybe a few things I forgot to mention, it must all be valid C code, though). Without such an interface, you cannot link C code with a C++ library.
The header of this pure C API needs to be compilable both with a C and a C++ compiler, however, when you compile it as C++, you must tell the C++ compiler that it is a C interface. That is why you need to wrap the entire API within
extern "C" {
//C API
}
when compiling as C++. However, that is not C code at all, so you must hide the extern "C" from the C compiler. This is done by adding the preprocessor directives
#ifdef __cplusplus1
extern "C" {
#endif
//C API
#ifdef __cplusplus1
}
#endif
If you cannot change your libraries header, you need to create a wrapper API that offers this pure C API and calls through to the respective C++ code.
How do I call C++ functions from C?
By writing calling functions whose declarations are valid in the common subset of C and C++. And by declaring the functions with C language linkage in C++.
The problem I'm having is that the api.h file contains references to namespaces
Such header is not written in common subset of C and C++, and therefore it cannot be used from C. You need to write a header which is valid C in order to use it in C.
Do I need to compile in C++ (ie using g++)?
If you have function definitions written in C++, then you need to compile those C++ functions with a C++ compiler. If you have C functions calling those C++ functions, then you need to compile those C functions with C compiler.
A minimal example:
// C++
#include <iostream>
extern "C" void function_in_cpp() {
std::cout << "Greetings from C++\n";
}
// C
void function_in_cpp(void);
void function_in_c(void) {
function_in_cpp();
}
You cannot. You can use C functions in your C++ program. But you cannot use C++ stuff from C. When C++ was invented, it allowed for compatibility and reuse of C functions, so it was written as a superset of C, allowing C++ to call all the C library functions.
But the reverse is not true. When C was invented, there was no C++ language defined.
The only way you can call C++ functions is to convert your whole project into a C++ one... you need to compile your C functions with a C++ compiler (or a C compiler if they are plain C) but for a C function to call a C++ function it must be compiled as C++. You should declare it with:
extern "C" {
void my_glue_func(type1 param1, type2 param2, ...)
{
/* ... */
}
} /* extern "C" */
and link the whole thing as a C++ program (calling the c++ linker)
This is because C doesn't know anything about function overloading, class initializacion, instance constructor calls, etc. So if you even can demangle the names of the C++ functions to be able to call them from C (you had better not to try this), they will probably run uninitialized, so your program may (most) probably crash.
If your main() function happens to be a C function, then there's no problem. C++ was designed with this thing in mind, and so, main() is declared implicitly as extern "C". :)

Read file fail when call C++ function in Swift code

guys.
I am writing an iOS app in swift, and I need to call some C++ lib. So I've build a simple example on how to bridge between C++ and Swift, and test on an iTouch. I wrapped the C++ interface with extern C. But I can't read the file when I call C++ function. Here is the code.
When I click the button on the iOS device, it needs to call the myFun():
main.swift
#IBAction func button(sender: AnyObject) {
myFun()
}
myFun() is my C++ function, which just reads a local file("hi.c").
DlibFun.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "DlibFun.h"
#include <unistd.h>
void myFun(){
char* path = (char*)"/hi.c";
FILE* f = fopen(path, "r");
if(f != NULL){
printf("open it\n");
fclose (f);
}else{
printf("FAIL\n");
}
}
Wrapper the C++ code in C
DlibFun.h
#ifdef __cplusplus
extern "C" {
#endif
int myFun();
#ifdef __cplusplus
}
#endif
photo-Bridging-Header.h
#include "DlibFun.h"
The result is that every time it prints out "FAIL". And any one give me any hint? I have tried the different path, but none of them are correct. Is it possible that my path is wrong? or there is any thicky thing that I don't know?
File folder
As you said, the code in the question is a simple example. I don't think the problem you are asking about, namely the fact that "FAIL" is output, is related to the real difficulties of bridging between C++ and Swift. The C++ function is called correctly, but the file can't be opened, most likely because it isn't there or isn't readable. In fact, I reproduced your example in Xcode, and got the output "open it" as long as the file was available; otherwise it would be "FAIL," as in your case.
Because DlibFun.cpp includes DlibFun.h, where myFun() is declared extern "C", the C++ compiler will compile myFun() to have C linkage, meaning it can be called from C and Swift. When Swift sees myFun() through the bridging header, it just treats it as a C function and calls it as such.
In a real-world situation, myFun() would be implemented in some C++ library and compiled using a C++ compiler, giving it C++ linkage, so just creating a header in Xcode, declaring myFun() extern "C", and then including the header in the bridge won't help. The build will fail with a link error.
To call the C++ library function myFun() you can write a wrapper as follows:
///////////////////
// File DlibFunW.h:
#ifndef DlibFunW_h
#define DlibFunW_h
// Because this is a C file for use by Swift code, via
// the bridge header, we don't need #ifdef __cplusplus.
// And because myFunW() was marked extern "C" in our C++
// wrapper, it's just a C function callable from Swift.
void myFunW();
#endif /* DlibFunW_h */
////////////////////
// File DlibFun.cpp:
#include "DlibFun.h"
// This file is C++ because it calls myFun(), which is
// a function with C++ linkage.
// This code is visible only to the C++ compiler, so
// we don't need #ifdef __cplusplus
extern "C" void myFunW() { myFun(); }
Now we don't need extern "C" in DlibFun.h, since myFun() has C++ linkage, as a real-world C++ library function would. The bridging header is now just
#include "DlibFunW.h"
and Swift calls myFunW() instead of myFun().
Of course, this is a very simple example dealing only with the C vs. C++ linkage problem. A real-world C++ function would take parameters and return values, often of pointer, struct, and class types, and dealing with those is a completely different can of worms. Here on StackOverflow you'll find plenty of info on that. Some questions I'd recommend:
Swift converts C's uint64_t different than it uses its own UInt64 type
How do I get a specific bit from an Integer in Swift?
Converting inout values to UnsafeMutablePointer<Unmanaged<TYPE>?>
Is it possible to convert a Swift class into C void* pointer?
Can I mix Swift with C++? Like the Objective - C .mm files
Hope you find useful info there, all the best!

C++, Wrapper function for sprintf_s

after including banned.h (one of microsoft security tools), the compiler gives me an warning that sprintf() function is not safe, and MSDN center gives me a suggestion to use sprintf_s, since my project is cross platform, I wrote a wrapper for sprintf function.
//safe function for sprintf();
void WrapperSprintf( char *buffer, const char *format, ... )
{
#ifdef _WIN32
sprintf_s(buffer, sizeof(buffer), format,...);
#else
sprintf(buffer, format, ...);
#endif
}
it gives me an error at line sprintf_s(buffer, sizeof(buffer), format,...);
error C2059: syntax error : '...'
Anyone knows how to write a wrapper function for sprintf_s()?
Thanks a lot.
The ... doesn't magically translate from the function declaration down to the other calls using those parameters. You have to include the variable arguments stuff and use that to call the next level down.
The steps are basically:
include the stdarg header.
declare a va_list.
call va_start.
call one of the v*printf functions.
call va_end.
For example, here's a little program that demonstrates how to provide a beast which writes the formatted output to a string, similar to what you seem to be after:
#include <stdio.h>
#include <stdarg.h>
void x (char *buf, char *fmt, ...) {
va_list va;
va_start (va, fmt);
vsprintf (buf, fmt, va);
va_end (va);
}
int main (void) {
char buff[100];
x (buff, "Hello, %s, aged %d", "Pax", 40);
printf ("%s\n", buff);
return 0;
}
Me, I tend to ignore Microsoft's suggestions about sprintf being unsafe. It's only unsafe if you don't know what you're doing and that can be said of any tool. If you want to become a good C programmer, you will learn the limitations and foibles of the language.
Including the one where you use sizeof on a char*, expecting it to return the size of the buffer it points to rather than the size of a pointer :-)
But, if you want to be a C++ developer, be a C++ developer. While C and C++ share a lot of commonality, they are not the same language. C++ includes a lot of C stuff primarily so that you can (mostly) take already-written C code and use it in your C++ applications.
In other words, if it's a C++ application, use std::string and std::stringstream(a) rather than char arrays and s*printf calls.
You should be writing your C++ code as if the C bits didn't exist. Otherwise, you're more a C+ programmer than a C++ one :-)
(a) Of course, knowledgeable developers will probably already be steering clear of the verbosity inherent in the stringstream stuff, and be using something like fmtlib (with the conciseness of printf but with the type safety C++ developers have come to appreciate).
Especially since it's being bought into C++20 where it will be part of the base, available to everyone.

Can i use C++ vectors in C code in VS2008

i am running c code in vs2008. I was curious if i can mix this code with c++ code
The short answer is yes. However, there are some nuances.
C++ generally supports a large subset of C. It means that you can almost anything available in C (such as functions, libraries etc) from C++ code. From this point you have two options, an easy one and a bit harder.
Option #1 - Use C++ compiler.
Just have your code treated as C++. Simply put - use C++ compiler.
Option #2 - Mix C and C++.
You can write your C code and compile it with C++ compiler. Use C-like C++ where you need to use C++ components. For example, you may have a setup similar to the following:
head1.h - declarations of your C functions. For example:
void foo1();
header2.h - declarations of your C functions that intend to use C++ code.
#ifdef __cplusplus
extern "C" {
#endif
void foo2 ();
#ifdef __cplusplus
}
#endif
And two source files, one C and one C++:
source1.c
#include "header1.h"
#include "header2.h"
void foo1 ()
{
foo2 (); /* Call a C function that uses C++ stuff */
}
source2.cpp
#include <vector>
#include "header2.h"
#ifdef __cplusplus
extern "C" {
#endif
void foo2 ()
{
std::vector<int> data;
/// ... etc.
}
#ifdef __cplusplus
}
#endif
Of course, you will have to compile "cpp" files with C++ compiler (but you can still compile "c" files with C compiler) and link your program with standard C++ runtime.
The similar (but slightly more complicated) approach is used by Apple, for example. They mix C++ and Objective-C, calling the hybrid Objective-C++.
UPDATE:
If you opt for compiling C code as C++, I recommend you spend some time studying the differences between C and C++. There are cases when the code could be both legal C and C++, but produce different results. For example:
extern int T;
int main()
{
struct T { int a; int b; };
return sizeof(T) + sizeof('T');
}
If it is a C program then the correct answer is 8. In case of C++ the answer is 9. I have explained this in more details in my blog post here.
Hope it helps. Good Luck!
If you are compiling your code using C++ compiler as a C++ program then you can use std::vector.
If you are compiling your code using C compiler as a C program then you cannot.
This is because std::vector is a type defined by the C++ Standard, C Standard does not define any type as std::vector.
In simple words a C compiler does not understand what std::vector is.
There is a switch to compile .c files as C++ (/TP) . If you enable this, you can use the c as C++. Beware that some c code will not compile as C++ without modification (mainly to do with type casting; c++ has stricter rules for this).
If you are interfacing with some existing C library, then you of course can use C++. If you are compiling as C though, you won't be able to use any C++ features, such as std::vector.

Calling C++ static member functions from C code

I have a bunch of C code. I have no intention to convert them into C++ code.
Now, I would like to call some C++ code (I don't mind to modify the C++ code so that they are callable by C code).
class Utils {
public:
static void fun();
}
class Utils2 {
public:
static std::wstring fun();
}
If I tend to call them with the following syntax, they wont compiled (I am using VC++ 2008, with C code files with .c extension)
Utils::fun();
// Opps. How I can access std::wstring in C?
Utils2::fun();
Any suggestion?
// c_header.h
#if defined(__cplusplus)
extern "C" {
#endif
void Utils_func();
size_t Utils2_func(wchar_t* data, size_t size);
#if defined(__cplusplus)
}
#endif
//eof
// c_impl.cpp
// Beware, brain-compiled code ahead!
void Utils_func()
{
Utils::func();
}
size_t Utils2_func(wchar_t* data, size_t size)
{
std::wstring wstr = Utsls2::func();
if( wstr.size() >= size ) return wstr.size();
std::copy( wstr.begin(), wstr.end(), data );
data[wstr.size()] = 0;
return str.size();
}
//eof
What about a wrapper
extern "C" void Utilsfun(int i){Utils::fun(i);}
Update:
That is how you can call C++ functions from C, but accessing std::wstring from C is a different matter.
If you really wanted to manipulate C++ classes from C code then you could create an API where the classes are operated on with C++ functions, and passed back to C using void pointers. I've seen it done, but it's not ideal
extern "C"
{
void * ObjectCreate(){return (void *) new Object();}
void ObjectOperate(void *object, char *parameter){((Object*)object)->Operate(parameter);}
void ObjectDelete(void *object){delete ((Object*)object);}
}
You will have to be very careful about managing creating and deleting.
The most common solution is to write a C interface to your C++ functions. That is C++ code which are declared using extern "C" { ... }. These wrapper functions are free to call any C++ code they like, but since they're declared extern "C", they won't be subject to name mangling (you can't do namespaces or overloading here).
That ought to be linkable with your C file and you're good to go.
That is, the header file contains
#ifdef __cplusplus
extern "C" {
#endif
void wrapper1(void);
int wrapper2(int x);
char* wrapper3(int y);
#ifdef __cplusplus
}
#endif
The ifdefs are required to shield the C compiler from the extern "C".
And you implement those in your C++ source
void wrapper1(void) { Util::funcOne(); }
int wrapper2(int x) { return Util::funcTwo(x); }
char* wrapper3(int y) { return Util::funcThree(y); }
Create a wrapper function in your C++ code:
extern "C" void Wrapper() {
Utils2::fun();
}
and then in your C code:
extern void Wrapper();
int main() {
Wrapper();
return 0;
}
I think the only solution is to wrap them in C style global functions in the C++ code like:
extern "C" int Util2_Fun() { return Util2::Fun(); }
I suppose you could also declare global function pointers as externs using some nasty variation of:
extern int (*Utils2_Fun)()=(int *())(Util2::Fun);
And then call the function pointer directly from the C package using this pointer but there is little to recommend this approach.
You can make C++ callable from C by using the extern "C" construct.
If you do as ppl say here (using extern "C") beware that you only pass objects to the C function that would compile in C.
You won't have any practical use for c++ objects in your C code, so you'll probably want to create some sort of "C Binding" for your C++ code which consists of some number of ordinary functions that are callable from the C, and only return ordinary C data types. Your wrapper functions can then call all sorts of classes and objects, etc. But, they provide a simpler C-Style interface for the objects that you can use from C to bridge the gap. You can also use function pointers in some cases to give the C access to static methods, but it's usually easiest just to create the wrapper, IMHO.
You can either write global extern "C" wrapper functions or use function pointers to additionally make static class functions known to C. The C++ code can put these pointers in a global structure or pass them to C while calling a C function as a parameter. Also, you could establish a registry where the C code can request function pointers from C++ by supplying a string id. I've these all these varieties being used.
If you have control of all of the source, I wouldn't bother trying to keep part of it as C. It should be compilable as C++ (or easily changed to make it so). That doesn't mean you need to rewrite it as C++, just compile it as such. This way you can use whatever parts of C++ make sense. Over time, the C code make turn more C++ like, but this will happen slowly as the need arises.
Of course, if you need it to remain compilable in C for other reasons, this doesn't apply.
C is a subset of C++ ..
So u can not call c++ Class members and namespaces in C.