I'v been trying to compile flann but this error shows up! ''va_list' has not been declared'
Can any one help me to solve this error?
Plz guild me so simple if u can, I'm really new in programming!
In file included from ./flann/nn/index_testing.h:41,
from ./flann/flann.hpp:43,
from src/common.hpp:12,
from src/main.cpp:9:
./flann/util/logger.h:74: error: 'va_list' has not been declared
Makefile:43: recipe for target `src/main.o' failed
make: *** [src/main.o] Error 1
Here is logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <cstdio>
#include "flann/general.h"
namespace flann
{
class Logger
{
FILE* stream;
int logLevel;
public:
Logger() : stream(stdout), logLevel(LOG_WARN) {};
~Logger()
{
if (stream!=NULL && stream!=stdout) {
fclose(stream);
}
}
void setDestination(const char* name)
{
if (name==NULL) {
stream = stdout;
}
else {
stream = fopen(name,"w");
if (stream == NULL) {
stream = stdout;
}
}
}
void setLevel(int level) { logLevel = level; }
int log(int level, const char* fmt, ...);
int log(int level, const char* fmt, va_list arglist);
int fatal(const char* fmt, ...);
int error(const char* fmt, ...);
int warn(const char* fmt, ...);
int info(const char* fmt, ...);
};
extern Logger logger;
}
#endif //LOGGER_H
You miss an include for the relevant macros
#include <cstdarg>
Related
#define LOG_INFO(str, ...) \
logger.NewLogStateMent(__FILE__, __LINE__, \
fver::base::log::Logger::LogLevel::kInfo, str, \
##__VA_ARGS__)
void NewLogStateMent(const char* filename, const int len, LogLevel lev, ...) {
std::cout << fmt::format("{} {} {} {} {}", filename, lne, lev, ...);
}
// use case
int main () {
LOG_INFO("hello, world %d", 1);
}
Now i want to this LOG_INFO(str, ...) to a fmt::format();
But the Gcc give me a lot of errors
gcc version: 12.2.0
c++ version: c++17
How can i finish it?
Please help me!
Something along these lines:
#define LOG_INFO(str, ...) \
NewLogStateMent(__FILE__, __LINE__, \
"info", str, \
##__VA_ARGS__)
template <typename... Args>
void NewLogStateMent(const char* filename, const int line, const char* level,
const std::string& format_str, Args&&... args) {
std::cout << fmt::format("{} {} {} ", filename, line, level)
<< fmt::format(fmt::runtime(format_str), std::forward<Args>(args)...);
}
// use case
int main () {
LOG_INFO("hello {} world", 1);
}
Demo
Here's how to do it with compile-time checks (https://godbolt.org/z/EE1zxcdrK):
#include <fmt/core.h>
#define LOG_INFO(str, ...) \
NewLogStatement(__FILE__, __LINE__, "info", str, ##__VA_ARGS__)
template <typename... T>
void NewLogStatement(const char* filename, int line, const char* level,
fmt::format_string<T...> fmt, T&&... args) {
fmt::print("{} {} {} ", filename, line, level);
fmt::print(fmt, std::forward<T>(args)...);
}
int main () {
LOG_INFO("hello {} world", 1);
}
I've been searching around for the answer to this but so far nothing has worked.
I have two files that were provided to me for a Parser assignment, lex.h and parse.h. The lex.h file was used in a previous assignment and works fine, the parse.h file is giving me issues. The parse.h file looks like this:
#ifndef PARSE_H_
#define PARSE_H_
#include <iostream>
#include <map>
using namespace std;
#include "lex.h"
//using std::map;
map<string, bool> defVar;
namespace Parser {
bool pushed_back = false;
LexItem pushed_token;
static LexItem GetNextToken(istream& in, int& line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return getNextToken(in, line);
}
static void PushBackToken(LexItem & t) {
if( pushed_back ) {
abort();
}
pushed_back = true;
pushed_token = t;
}
}
static int error_count = 0;
void ParseError(int line, string msg)
{
++error_count;
cout << line << ": " << msg << endl;
}
extern bool Prog(istream& in, int& line);
extern bool StmtList(istream& in, int& line);
extern bool Stmt(istream& in, int& line);
extern bool PrintStmt(istream& in, int& line);
extern bool IfStmt(istream& in, int& line);
extern bool Var(istream& in, int& line);
extern bool AssignStmt(istream& in, int& line);
extern bool ExprList(istream& in, int& line);
extern bool Expr(istream& in, int& line);
extern bool Term(istream& in, int& line);
extern bool Factor(istream& in, int& line);
#endif /* PARSE_H_ */
Analyzer Class
#include <regex>
#include "lex.h"
/**
* Relates token type to string
*/
static std::map<Token, std::string> tokenPrint {
// Code not provided for readability
};
/**
* Operator overloading << for Token object
*/
ostream& operator<<(ostream& out, const LexItem& tok) {
// Code not provided for readability
}
/**
* Current token is used to set previous token before returned
* Previous token is used to compare to the current token and check
* for invalid arangment such as no begin token.
*/
LexItem currentToken;
LexItem previousToken;
/**
* Return the next token within a file
*/
LexItem getNextToken(istream& in, int& linenum) {
enum TokenState { START, INID, INSTRING, ININT, INREAL, INCOMMENT, SIGN} lexstate = START;
std::string lexeme;
char character;
// Code not provided for readability
}
Parse.cpp
#include "parse.h"
bool Prog(istream& in, int& line) {
return false;
}
bool StmtList(istream& in, int& line) {
return false;
}
// All the rest return false too
Tester.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
#include "parse.h"
int main(int argc, char** argv) {
// Reads file and handles errors
// Code not provided for readability
while (true) {
Parse::getNextToken(file, lineNumber);
}
}
I have an Analyzer.cpp file that uses lex.h as a header for the Analyzer and I have a Parse.cpp that uses parse.h for the Parser. In the main program I use the parse.h header file.
I keep getting a multiple definition error with defVar, Parse::pushed_back, Parser::pushed_token, and ParseError(...). I cannot edit lex.h or parse.h as they are given to me and can only change the contents of Analyzer.cpp, Parser.cpp, and Tester.cpp. I can post all the code if necessary.
I'm fairly new to c++ but all the header files have the header guards and none of the functions are ever defined twice. I have looked at other problems but nothing seems to be working. Any help is greatly appreciated.
I am trying to make a nested function call with a variable number of parameters without retrieving them. And I get the wrong result.
Here is my simple c++ program:
extern "C" {
#include <stdio.h>
}
#include <cstdarg>
class ctty {
public:
ctty();
int logger(int prior, const char* format, ...);
private:
};
ctty::ctty(){};
int ctty::logger(int prior, const char* format, ...)
{
va_list ap;
va_start(ap,format);
printf(format, ap);
va_end(ap);
return 0;
}
int main(int argc, char** argv)
{
ctty tty;
tty.logger(0, "Test %d %d %d\n", 7, 5, 5);
return 0;
}
result:
Test -205200 7 5
I expect a result
Test 7 5 5
I don’t understand what am I doing wrong?
Thanks in advance.
You can't directly pass va_list to printf. va_list is a wrapper around the actual list of arguments (whatever its representation is). Although C way to do should be to use vprintf, in C++ there are safer alternatives, like variadic templates allowing to create a safer version of formatted printing, e.g. (a fictional format string for brevity of example):
#include <iostream>
#include <cstdlib>
class ctty {
public:
ctty();
template<typename T, typename... Args>
int logger(int prior, const char* format, T value, Args... args);
private:
void logger(int prior, const char *s);
};
ctty::ctty(){};
void ctty::logger(int prior, const char *s)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
throw std::runtime_error("invalid format string: missing arguments");
}
}
std::cout << *s++;
}
}
template<typename T, typename... Args>
int ctty::logger(int prior, const char* format, T value, Args... args)
{
while (*format) {
if (*format == '%') {
std::cout << value;
logger(prior, format + 1, args...);
return 0;
}
std::cout << *format++;
}
throw std::logic_error("extra arguments provided to logger");
}
int main(int argc, char** argv)
{
ctty tty;
tty.logger(0, "Test % % %\n", 7.55f, "Tada!", 888);
return 0;
}
This part of your code:
extern "C" {
#include <stdio.h>
}
Is technically an undefined behavior, while it may compile and not have adverse effect in some cases, it's not portable. You have to use C++ headers, e.g. <cstdio>
I'm having some problems with my code. A shared library is causing an undefined symbol error that I just cannot figure out. All of the files are in the correct locations and the shared library builds successfully but upon executing the program it returns the bellow message.
The error message:
libsp.so: undefined symbol: _ZTIN4Poco20NullPointerExceptionE
From what I can see the problem is the Poco headers I use. The headers I got from an outside source and they should all work, I believe the error is caused by how I call these headers, but I might be wrong.
Bellow is the only code that uses Poco in the libsp library. And the code of the 4 header files I use. I've checked and rechecked and cannot find any issues but am still getting the undefined symbol exception.
File Spexec.cpp (libsp):
#include "../poco/Poco/Base64Encoder.h"
#include "../poco/Poco/DigestEngine.h"
#include "../poco/Poco/MD5Engine.h"
#include "../poco/Poco/Path.h"
using namespace std;
stringstream s_base;
Poco::Base64Encoder encoder(s_base);
Poco::Path path(data.name);
data.path = data.name.substr(0, data.name.length() - path.getFileName().length());
Poco::MD5Engine md5;
stringstream ss;
ss << data.created << data.name;
md5.update(ss.str());
data.name = Poco::DigestEngine::digestToHex(md5.digest());
}
File Base64Encoder.h:
#ifndef Foundation_Base64Encoder_INCLUDED
#define Foundation_Base64Encoder_INCLUDED
#include "Foundation.h"
#include <ostream>
namespace Poco {
class Foundation_API Base64Encoder:, public std::ostream
{
public:
Base64Encoder(std::ostream& ostr);
~Base64Encoder();
private:
Base64Encoder(const Base64Encoder&);
Base64Encoder& operator = (const Base64Encoder&);
};
} // namespace Poco
#endif // Foundation_Base64Encoder_INCLUDED
File DigestEngine.h:
#ifndef Foundation_DigestEngine_INCLUDED
#define Foundation_DigestEngine_INCLUDED
#include "Foundation.h"
#include <vector>
namespace Poco {
class Foundation_API DigestEngine
{
public:
typedef std::vector<unsigned char> Digest;
DigestEngine();
virtual ~DigestEngine();
void update(const void* data, std::size_t length);
void update(char data);
void update(const std::string& data);
virtual std::size_t digestLength() const = 0;
virtual void reset() = 0;
virtual const Digest& digest() = 0;
static std::string digestToHex(const Digest& bytes);
static Digest digestFromHex(const std::string& digest);
presentation
protected:
virtual void updateImpl(const void* data, std::size_t length) = 0;
private:
DigestEngine(const DigestEngine&);
DigestEngine& operator = (const DigestEngine&);
};
File MD5Engine.h:
#ifndef Foundation_MD5Engine_INCLUDED
#define Foundation_MD5Engine_INCLUDED
#include "Foundation.h"
#include "DigestEngine.h"
namespace Poco {
class Foundation_API MD5Engine: public DigestEngine
{
public:
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 16
};
MD5Engine();
~MD5Engine();
std::size_t digestLength() const;
void reset();
const DigestEngine::Digest& digest();
protected:
void updateImpl(const void* data, std::size_t length);
private:
static void transform(UInt32 state[4], const unsigned char block[64]);
static void encode(unsigned char* output, const UInt32* input, std::size_t len);
static void decode(UInt32* output, const unsigned char* input, std::size_t len);
struct Context
{
UInt32 state[4]; // state (ABCD)
UInt32 count[2]; // number of bits, modulo 2^64 (lsb first)
unsigned char buffer[64]; // input buffer
};
Context _context;
DigestEngine::Digest _digest;
MD5Engine(const MD5Engine&);
MD5Engine& operator = (const MD5Engine&);
};
}
File Path.h:
#ifndef Foundation_Path_INCLUDED
#define Foundation_Path_INCLUDED
#include "Foundation.h"
#include <vector>
namespace Poco {
class Foundation_API Path
{
public:
enum Style
{
PATH_UNIX, /// Unix-style path
PATH_WINDOWS, /// Windows-style path
PATH_VMS, /// VMS-style path
PATH_NATIVE, /// The current platform's native style
PATH_GUESS /// Guess the style by examining the path
};
typedef std::vector<std::string> StringVec;
Path();
Path(const char* path);
Path(const std::string& path);
protected:
void parseUnix(const std::string& path);
void parseWindows(const std::string& path);
void parseVMS(const std::string& path);
void parseGuess(const std::string& path);
std::string buildUnix() const;
std::string buildWindows() const;
std::string buildVMS() const;
private:
std::string _node;
std::string _device;
std::string _name;
std::string _version;
StringVec _dirs;
bool _absolute;
};
I am using libxml2 to validate an xml file against an xsd schema.
Using xmlSchemaSetParserErrors function, errors are output to stderr.
I need to get these validation errors, store them in memory and display to the user.
How can I redirect these errors ? Could you provide me some examples ?
Thanks,
Andrea
This example uses the validation callback mechanism of the parser module. The signature of callbacks expected by xmlSchemaSetParserErrors seems to be the same.
#include <iostream>
#include <cstdarg>
#include <cstdio>
#include <vector>
#include <string>
#include <iterator>
#include <libxml/parser.h>
#include <libxml/tree.h>
struct ParserContext
{
ParserContext() : context(xmlNewParserCtxt()) {}
~ParserContext() { xmlFreeParserCtxt(context); }
xmlParserCtxtPtr context;
private:
ParserContext(ParserContext&);
void operator=(ParserContext&);
};
struct ErrorHandler
{
std::vector<std::string> errors;
void RegisterErrorHandling(xmlValidCtxt& validationContext)
{
// Change this to register for schema errors...
validationContext.userData = this;
validationContext.error = &ErrorHandler::Handle;
}
private:
static void Handle(void *handler, const char *format, ...)
{
va_list arguments;
va_start(arguments, format);
std::string message = MakeMessage(format, arguments);
va_end(arguments);
ErrorHandler* errorHandler = static_cast<ErrorHandler*>(handler);
errorHandler->errors.push_back(message);
}
static std::string MakeMessage(const char* format, va_list arguments)
{
const size_t bufferSize = 200;
std::vector<char> buffer(bufferSize, 0);
size_t charactersWritten =
vsnprintf(&buffer.front(), bufferSize, format, arguments);
if (charactersWritten == -1)
buffer.back() = 0; // Message truncated!
return std::string(&buffer.front());
}
};
struct XmlDocument
{
static XmlDocument FromFile(const char* fileName)
{
ParserContext parser;
ErrorHandler errorHandler;
errorHandler.RegisterErrorHandling(parser.context->vctxt);
XmlDocument document(xmlCtxtReadFile(
parser.context, fileName, NULL, XML_PARSE_DTDVALID));
document.errors = move(errorHandler.errors);
return document;
}
XmlDocument(XmlDocument&& other) :
xmlPointer(other.xmlPointer),
errors(move(other.errors))
{
other.xmlPointer = nullptr;
}
~XmlDocument()
{
xmlFreeDoc(xmlPointer);
}
xmlDocPtr xmlPointer;
std::vector<std::string> errors;
private:
XmlDocument(xmlDocPtr pointer) : xmlPointer(pointer) {}
XmlDocument(XmlDocument&);
void operator=(XmlDocument&);
};
void DisplayErrorsToUser(
const XmlDocument& document,
std::ostream& displayStream = std::cout)
{
using namespace std;
copy(begin(document.errors), end(document.errors),
ostream_iterator<string>(displayStream, "\n"));
}
int main()
{
auto xml = XmlDocument::FromFile("test.xml");
DisplayErrorsToUser(xml);
}
Or even more concise:
void err(void *ctx, const char *msg, ...)
{
va_list args;
va_start(args, msg);
char *val = va_arg(args,char*);
va_end(args);
}
val now contains validation errors
As said in the API documentation, xmlSchemaSetParserErrors() Set the callback functions used to handle errors for a validation context.
You need to write two callback functions with respect to defined signature :
xmlSchemaValidityErrorFunc err
xmlSchemaValidityWarningFunc warn
An example could be :
void err(void *ctx, const char *msg, ...)
{
char buf[1024];
va_list args;
va_start(args, msg);
int len = vsnprintf_s(buf, sizeof(buf), sizeof(buf)/sizeof(buf[0]), msg, args);
va_end(args);
if(len==0) // Can't create schema validity error!
else // Do something to store `buf`,
// you may need to use void *ctx to achieve this
return;
}
Then just call
xmlSchemaSetValidErrors(valid_ctxt_ptr, (xmlSchemaValidityErrorFunc) err, (xmlSchemaValidityWarningFunc) warn, ctx);
before calling
xmlSchemaValidateDoc()