Say I have a function like
void printToSomewhere(FILE* stream, char* msg){
fprintf(stream, "%s", msg);
}
If I want the stream to be stdout, do I have to declare that before in the calling function:
...
FILE* stdout;
printToSomewhere(stdout, "printing to stdout");
...
or can I call the function without having to define/include/etc stdout explicitly?
...
printToSomewhere(stdout, "printing to stdout");
...
As with every variable, you have to declare stdout before using it. The variable stdout is declared in the header file stdio.h (or cstdio in C++). By including stdio.h (or cstdio), stdout becomes visible.
On many platforms, you can also simply declare stdout as an extern variable:
extern FILE *stdout;
although doing so is discouraged, as the C standard requires stdout to be a macro and allows it to expand to something that is not even a variable. On most plaforms however, stdio.h defines this macro simply as
#define stdout stdout
but you should refrain from making this assumption in portable software.
Yes. STDOUT is always file descriptor 1 (mandated by POSIX).
This will work:
#include <stdio.h>
#include <stdlib.h>
void printToSomewhere(FILE* stream, const char* msg){
fprintf(stream, "%s", msg);
}
int main()
{
FILE* f = fdopen(1, "w+");
printToSomewhere(f, "Hello\n");
fclose(f);
return 0;
}
expected output:
Hello
Related
I have a c and cpp file
mycpp.cpp
fun()
{
//code goes here....
}
mycpp.h
#include<string>
struct str{
std::string a;
};
func();
myc.c
#include "mycpp.h"
func();
//with other c codes..
This is a part of large code list. So it gets compiled via c++ and c.
My problem is when mycpp.h is compiled through myc.c (which is included in myc.c) , Compiler throws an error saying fatal error: string: No such file or directory
Is there some wrapper mechanism to overcome this scenario?
You cannot include a C++ header file in a C file.
Declare the function func() with C linkage, and refer to it as an extern function inside your C file.
Example:
mycpp.cpp
void func(void)
{
/* foo */
}
mycpp.h
extern "C" void func(void);
myc.c
extern void func(void);
/* you can now safely call `func()` */
You cannot use std::string in C, if you want to access your string, you have to pass it accordingly into your C code, by passing it a char const* with the contents of the string. You can get access to this string by calling std::string::c_str(). You can read more about c_str() here.
sprintf is an API provided by platform. I want to filter some format when it is used. My idea is:
#include <stdio.h>
int my_sprintf(...)
{
my_filter_function(...);
return ::sprintf(...);
}
#define sprintf my_sprintf
Then put these code in pch.
But I am still worrying it can't cover all usages, some one is in prebuilt library and not every project has a pch. Do you have any other idea?
Thanks. It's on windows.
You can't "overwrite" a built-in function. Furthermore, using a macro to replace its name results in your program having undefined behaviour.
So, don't even try to change the behaviour of the standard library. Really, that way madness lies.
Just call my_sprintf from your own code and let the platform do what it always did.
You want to use variadic functions.
Example:
int my_sprintf(char *buffer, char *fmt, ...)
{
int ret;
va_list args;
va_start(args, fmt);
/* insert your filter here */
/* you CAN NOT re-use a va_list variable after being used */
ret = vsprintf(buffer, fmt, args);
va_end(args);
return ret;
}
Note: You are not allowed to define a function / macro with the same name as a function from the standard library. It's undefined behaviour.
You have to replace all your calls to sprintf with your custom my_sprintf function.
You can use namespace concept to define functions with the same names
#include <stdio.h>
namespace myns
{
int sprintf(...)
{
my_filter_function(...);
return ::vsprintf(...);
}
}
than call
char buffer[256];
myns::sprintf(buffer, "Hello, %s!\n", "World");
So I have looked here and here and at a few other links mentioned in the first question and I have the following code already:
The .cpp file:
#include "arp_piping.h"
#include <string>
#include <iostream>
#include <stdio.h>
std::string exec(char* cmd, FILE* pipe) {
pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
The header/linker file:
#ifndef ARP_PIPING_H
#define ARP_PIPING_H
#endif
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
my function goes here something like
EXTERNC .....exec(char* cmd, FILE* pipe) ????
#undef EXTERNC
My question is what goes in the bit above as I am unsure what to be typing. I am trying to call the function in the .cpp file from my C main function int main(int argc, char** argv) {}
To call C++ functions from C you need to do two things. 1) Let the C++ code know it's going to be used by C so that it can generate C-friendly symbols. 2) Hide any functionality that C can't understand.
The first part is easily achieved by simply defining the functions as you would in C (I.E. don't use any C++ only features like namespaces) and then wrapping them in an extern "C" block if C++ is defined. You basically want your header file to contain C-only code, and then just open the extern block at the top, and close it at the bottom of the file (my example will make this more clear).
The second part is a little trickier, but not too difficult. In your case, your function returns a std::string which is a C++ only class. It can not be used in C and therefore either needs to be replaced with something that can be used in C, or it needs to be hidden behind something that C can use. For the sake of argument let's assume you can't replace std::string with say, char*. In this case you need to hide std::string from the C-facing code. The common way of doing this is to use an opaque pointer.
Basically, the C-facing code deals only with a pointer to something. That something it neither knows about, nor cares about. The C++ code is free to use a std::string internally, but must make sure to hide it before interfacing with the C API. In my example, you can see I've provided an opaque pointer to a struct I've called cppstring.
In the source file, cppstring is just a struct that holds a std::string. I've changed your example code to use the new cppstring struct. One important thing to note is that because the C code can only deal with a pointer to a cppstring, we need to create it on the heap in our C++ code and return the pointer to it. This means that we must provide the C users some way of freeing it when they're done, which I've also provided in the example.
Using this technique you can wrap the entirety of std::string behind a C API, allowing C users to use all of the functionality that std::string provides. I've provided an example of wrapping std::string::substr to show you how.
N.B. I haven't compiled nor tested this code and for the sake of simplicity I haven't included any of the relevant header files, etc. Nevertheless, it should be enough to get you started.
// C header
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cppstring *cppstring_p;
cppstring_p exec(char *cmd, FILE *pipe);
void free_cppstring(cppstring_p cppstr);
/* example of wrapping std::string::substr for C users */
cppstring_p substr(cppstring_p str, int pos, int count);
#ifdef __cplusplus
}
#endif
// CPP source
struct cppstring {
std::string data;
cppstring(void) {}
cppstring(std::string const& s) : data(s) {}
};
cppstring_p exec(char *cmd, FILE *pipe) {
pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
auto result = new cppstring;
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result->data += buffer;
}
_pclose(pipe);
return result;
}
void free_cppstring(cppstring_p cppstr) {
delete cppstr;
cppstr = nullptr;
}
cppstring_p substr(cppstring_p str, int pos, int count) {
assert(str);
return new cppstring(str->data.substr(pos, count));
}
You need to declare the function as extern "C" in the cpp file:
extern "C" char *exec(char* cmd, FILE* pipe) {
...
}
In the header/linker file you need to declare it's prototype with the keyword "extern", like so:
extern char *exec(char* cmd, FILE* pipe);
Also, are you sure you want to return a c++'s std::string to your C code?
I have three files as below
Test.cpp
void helloworld()
{
disable pf;
pf.Disable();
printf("No statement \n");
}
int main()
{
disable dis;
helloworld();
printf("Hello World");
system("pause");
return 0;
}
disable.cpp
#include "StdAfx.h"
#include "disable.h"
disable::disable(void)
{#define printf(fmt, ...) (0)}
disable::~disable(void)
{}
void disable::Disable()
{
#define printf(fmt, ...) (0)
}
disable.h
#pragma once
class disable
{
public:
disable(void);
~disable(void);
void Disable();
};
After executing, I am getting output as No Statement Hello World.
But I would like to disable these two printf statements by calling Disable function and disable constructor..
Please help me why it is not working and how to solve this. Please help.
But things works fine if I do like
main()
{
#define printf(fmt, ...) (0)
printf("Hello World");
}
But why not if I am calling it from a function?
You can disable the printf ouput by:
close(STDOUT_FILENO);
or you can use also:
fclose(stdout);
This will disable all output to the stdout
Example:
#include<stdio.h>
#include<stdlib.h>
int main(){
printf ("This message will be displayed\n");
fclose(stdout);
printf ("This message will not be displayed\n");
// to reopen the stdout, this is another question
return 0;
}
Note
If you are using sockets in your program, than you have to be careful here because the close of stout will cause the redirection of the output to the sockets
A macro doesnt obey scope rules, c++ syntax rules, or anything. It is a text replacement engine, only.
When you say #define printf(fmt, ...) (0) in disable.cpp, it is defined ONLY in disable.cpp. If you were to write that in disable.h, it would be defined in all files that include from disable.h.
The only way to control a macro is with a macro (#if and #ifdef and their ilk). So what you want to to can be achieved by the following.
#define DISABLE_PRINTF
#ifdef DISABLE_PRINTF
#define printf(fmt, ...) (0)
#endif
But this will be a global disable and can only be undone by commenting out the first #define and recompiling the code. There is no way to do selective/scope based control of disabling using macros.
Edit: Instead of redefining printf itself, it is recommended to write a wrapper which is defined in terms of printf for this purpose.
On implementations that support it, you could redirect the stdout buffer to "disable" the console, and restore it when you want to "enable" it again. Here's a code sample which works (at least) on Linux with gcc.
NOTE This is a implementation-specific solution and uses dup() and dup2() from unistd.h. It is not guaranteed by the standard to work everywhere.
#include <cstdio>
#include <unistd.h>
int main() {
printf("Hello world.\n");
fpos_t pos;
fgetpos(stdout, &pos); // save the position in the file stream
int fd = dup(fileno(stdout)); // use the dup() function to create a copy of stdout
freopen("dummy.txt", "w", stdout); // redirect stdout
printf("Hello nobody.\n"); // this is not printed to the "usual" stdout
fflush(stdout);
dup2(fd, fileno(stdout)); // restore the stdout
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); // move to the correct position
printf("Hello world again.\n"); // this is printed back to the "usual" stdout
}
You could put that logic into enable() and disable() functions.
Let me emphasise, this is an implementation-specific solution. I am not aware of any standard-conforming solution to restore the standard streams after they have been redirected.
I was wanting to use a constant of some kind for the application ID (so I can use it in printf).
I had this:
#define _APPID_ "Hello World!"
And then the simple printf, calling it into %s (string). It put this out:
simple.cpp:32: error: cannot convert ‘_IO_FILE*’ to ‘const char*’ for argument ‘1’ to ‘int printf(const char*, ...)’
What would I use to define the application ID to use in printf? I tried:
static const char _APPID_[] = "Hello World"`
but it didn't work, same error I think.
I'm not sure I understand exactly what you tried... but this works:
#include <stdio.h>
#define _APPID_ "Hello world"
int main()
{
printf("The app id is " _APPID_ "\n");
/* Output: The app id is Hello world */
return 0;
}
When presented with two constant strings back to back (i.e. "hello " "world"), the compiler treats them as a single concatenated constant string ("hello world").
That means that in the case of trying to printf a compile-time constant string, you don't need to use printf("%s", _APPID_) (although that should still work).
According to the error message, the problem is most likely not caused by the string constant, but by incorrect parameters given to printf().
If you want to print to a file, you should use fprintf(), not printf(). If you want to print to the screen, use printf(), but don't give a file handle as its first parameter.
In source.h
#ifndef _SOURCE_H
#define SOURCE_H
#ifdef APP_ID
#define WHOAMI printf("%s\n", APP_ID);
#endif
#endif
In your program:
#define APP_ID __FILE__
#include "source.h"
int main()
{
WHOAMI
return 0;
}
the reason for this is to have a stadnard include file - source.h. __FILE__ inside a header file returns the name of the header file, so the APP_ID definition is constrained to live in the C file.
If you don't define APP_ID the code won't compile.
_APPID_ is a name that's reserved for the implementation. It matches the pattern ^_[A-Z].*
Rename it to e.g. APP_ID.