How to convert void* to foo* to comply with C++? - c++

I am trying to compile a code written in C (ndpiReader.c program that comes with nDPI library, hosted here). I'm using Qt Creator and GCC compiler.
After doing some research here and here, I notice that compiling C code with C++ compiler is not the best idea. But I didn't get the answer of how to do this conversion and make this code C++ compatible.
When I try to run the code in Qt Creator I get the error bellow:
error: invalid conversion from 'void*' to 'ndpi_flow_struct*' [-fpermissive]
if((newflow->ndpi_flow = malloc_wrapper(size_flow_struct)) == NULL) {
^
If more info is needed to solve the problem please leave a comment. I'm new to C++ so detailed answers with links are so much appreciated.
Edit: here is malloc_wrapper() function's code
static void *malloc_wrapper(unsigned long size) {
current_ndpi_memory += size;
if(current_ndpi_memory > max_ndpi_memory)
max_ndpi_memory = current_ndpi_memory;
return malloc(size);
}

You're seeing this error because in c++, types should have an exact match.
As we can see, the malloc_wrapper() function returns a void * and your newflow->ndpi_flow is of type ndpi_flow_struct*. So while compiling using c++ compiler, you've to add the cast, like
if((newflow->ndpi_flow=(ndpi_flow_struct*)malloc_wrapper(size_flow_struct)) == NULL) { . . .
to force the compiler in believing that the return value of malloc_wrapper() is of type (ndpi_flow_struct*).
or even better, the static cast<> (keeping in mind the C++ aspect), like
if(( newflow->ndpi_flow =
static_cast<ndpi_flow_struct*>malloc_wrapper(size_flow_struct)) == NULL) { . . .
Related Reading: A detailed answer on C++ Casting.

Usually, we just write
if((newflow->ndpi_flow = (ndpi_flow_struct*)malloc_wrapper(size_flow_struct)) == NULL) {

Related

Malloc C and C++ code compatibility

I have made a program that contains the following function in C:
void *e_malloc(size_t size)
{
void *m = malloc(size);
if (!m)
{
printf("Out of memory, fatal error.");
abort();
}
return m;
}
I am using this as an error free malloc that exits the program when out of memory. The thing is, that when I compile the code in linux with g++, I get an error because it says that it needs to be casted, and as you can see I always return a void pointer cause that's what malloc returns (gcc of course compiles fine). Is there a way I could modify this function to make it work on both compilers ? Do I just have to cast it every time ? Are there other options to make what I am trying to do ?
Also, when I use Cmake (through Clion IDE) the code compiles just fine with "-std=C++11". Why is that ?
You could make it easier to use with macros:
#define e_new(type) ((type*)malloc(sizeof(type)))
#define e_new_array(type, count) ((type*)malloc((count)*sizeof(type)))
example usage:
graph_t *g = e_new(graph_t);
graph_t *ten_gs = e_new_array(graph_t, 10);
Note that this is not specific to your e_malloc - malloc itself has the same problem in C++.
As the compiler error clearly states, the error is in your calling code, not in your e_malloc.
You probably have something like this:
graph_t *g;
g = e_malloc(sizeof(graph_t));
The error is the type conversion between the void * returned by e_malloc and the expected graph_t*. Regular malloc shows the same behavior. You need to do the typecast explicitly:
g = (graph_t*)e_malloc(sizeof(graph_t));
You should not be using this construct in C++ at all. In C++, you need to use new, not malloc - and new already throws an exception (by default). Problem solved.

Handle errors C++

So, I have a simple library-class and this class has some methods that return some values like code errors.
User_program
MyClass go(arg1, arg2)
if(go.execute() == 0)
std::cout << go.result();
And my class has something like this
My class
int execute()
{
if((temp = doBar()) != 0)
{
return temp;
}
return SUCCESS;
}
int doBar()
{
if(foo == 1)
return DIVIDION_BY_ZERO;
if(fzz == 0)
return OPERATION_ERROR;
}
And so on. So, is there any method to make errors more helpful, I've heard about enum with const for errors, but I don't understand how to implement it.
Thanks.
Not sure that I understood the question right, but here is few moments.
In your case enum`s is way to store all definitions of const
values like (SUCCESS, DIVIDION_BY_ZERO, etc) in one place (even in
one translation unit). And also compiletime validation of types.
read more here:
[1]
2) If intresting how implemented some error check there is no need
to go far.
First of all look at C handling errors in libc [2]
In ISO C++11 presented [system_error]
And typical error handling in libs released special for (almost) each type like in Qt [QNetworkReply]
And also using exceptions(and dark side of C++ like RTTI) in libs is bad idea. But take this link too [3]

Access pre-compiled functions within a class C++/11

Sorry if the title is misleading, I'm currently looking for solutions to the following:
I'm developing a library, for other people to use. They have to follow a strict design concept and the way they structure any additional features within the library. They all use Linux and (Vim) and as such as are allowed to use terminal commands (i.e to be able to compile etc..) and we all use clang as a compiler.
My question is this: Let's suppose I write a function called: "checkCode":
template<typename T>
void checkCode(T&& codeSnippet)
{
//// code
}
I want to make this function run so whenever they type "checkCode" in a terminal this function is therefore called. I know using clang thy have similar functionality, however, this is understandable as you're using the whole of clang. So:
1) Is it possible to just compile a class, and then access each of the functions through
the .dylab | .so file?
2) Might it be a better idea, or, better to take a copy of the source of clang, add this functionality and role it out to those using and contributing to the library? This would be like an additional add-on to clang?
Thanks
you could use one executable and symbolic links to it like busybox:
int main(int argc, char **argv)
{
string programName = argv[0];
size_t lastSlash = programName.find_last_of('/');
if(lastSlash != string::npos)
programName = programName.substr(lastSlash + 1);
if(programName == "function_1")
{
function_1();
return 0;
}
if(programName == "function_2")
{
function_2();
return 0;
}
// ...
// normal main code
return 0;
}

Segmentation fault when testing migrated library from qt4 to qt5

I am testing this library but I am getting a segmentation fault whenever it reachs a certain line (the commented one below). This issue comes from this question - tldr the same problem on a much bigger project, so I decided to test the libraries separatedly and apparently this is what fails. This code works on a co-worker's 32bits machine using Qt4 (he handed me the code). I migrated it to Qt5 and compiled with a 32bit compiler and I am getting the segmentation fault. If I comment the offending line and the two below it the program runs (although its just an empty window).
What could be happening?
#include "qenctest.h"
#include <QLibrary>
#include <QtWidgets/QMessageBox>
typedef void (*encRefresh)(QPainter*);
encRefresh enc_refresh = NULL;
typedef void (*encResize)(QSize);
encResize enc_resize = NULL;
typedef QENCSignaler* (*encInit)(QString);
typedef void (*encOpenFile)(QString);
QENCTest::QENCTest(QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QLibrary _qenc("qenc");
encInit enc_init;
encOpenFile enc_openFile;
enc_init = (encInit) _qenc.resolve("init"); // I checked and it does load the library and the symbol succesfully
enc_openFile = (encOpenFile) _qenc.resolve("openFile");
enc_resize = (encResize) _qenc.resolve("resize");
enc_refresh = (encRefresh) _qenc.resolve("refresh");
QString path = "encfg";
QENCSignaler* qencSignaler = enc_init(path); // Throws segfault here
connect(qencSignaler, SIGNAL(newChart(Chart*)), this, SLOT(qencNewChart(Chart*)));
connect(qencSignaler, SIGNAL(startReadChart(char*)), this, SLOT(qencStartReadChart(char*)));
enc_openFile("PL2BAPOL.000");
int _s = 0;
}
Debug info:
PS: What does it mean that some locals & expressions are in red?
EDIT
Alright, the only major changes I had to make in the library code were these:
AttributeSet::iterator vItPOI = attributes.at(i).find("POI");
if (vItPOI == attributes.at(i).end()) continue;
AttributeSet::iterator vItPOI0 = attributes.at(i).find("POI0");
if (vItPOI0 == attributes.at(i).end()) continue;
if (vItPOI -> getStringValue() == "Bankowoæ" &&
selectedPOI & POI_BANKING) {
if (vItPOI0 -> getStringValue() == "Placówka banku") {
drawSymbol(painter, x, y, POI_BANKING);
}
}
To this (there are more ifs but this illustrates it properly)
ShapeAttribute vItPOI = attributes.at(i).find("POI").value();
if (attributes.at(i).find("POI") == attributes.at(i).end()) continue;
ShapeAttribute vItPOI0 = attributes.at(i).find("POI0").value();
if (attributes.at(i).find("POI0") == attributes.at(i).end()) continue;
if (vItPOI . getStringValue() == "Bankowo��" &&
selectedPOI & POI_BANKING) {
if (vItPOI0 . getStringValue() == "Plac�wka banku") {
drawSymbol(painter, x, y, POI_BANKING);
}
}
In theory it should be the same shouldnt it? Although I do find strange that in the first snippet it uses -> instead of . when its not a pointer. I had to change it to that because I was getting these errors:
^
..\qenc\ShapeLandPOI.cpp: In member function 'virtual void ShapeLandPOI::draw(QPainter*)':
..\qenc\ShapeLandPOI.cpp:74:62: error: conversion from 'QMap<QString, ShapeAttribute>::const_iterator' to non-scalar type 'QMap<QString, ShapeAttribute>::iterator' requested
AttributeSet::iterator vItPOI = attributes.at(i).find("POI");
^
..\qenc\ShapeLandPOI.cpp:76:64: error: conversion from 'QMap<QString, ShapeAttribute>::const_iterator' to non-scalar type 'QMap<QString, ShapeAttribute>::iterator' requested
AttributeSet::iterator vItPOI0 = attributes.at(i).find("POI0");
^
In your changed code you have the line
ShapeAttribute vItPOI0 = attributes.at(i).find("POI0").value();
But if "POI0" is not found the find function would return end which is an iterator pointing to beyond the collection, and so it's value function would be causing undefined behavior.
As for the errors it seems that the QMap object is constant, and so you can't get non-const iterators. Just change to use AttributeSet::const_iterator instead and you can use the original function otherwise unmodified. This will probably fix your crashes, as then you don't have the risk of undefined behavior as described above.

C++ Function Pointer

Is this possible? If so, I can't seem to get the syntax right. (C++ function pointer)
bit of background. The code below has been shorten for this post. The reason for this implementation is to avoid an endless list of SWITCH/CASE or IF/ELSEIF statements; and have an endless list of DECODER_FUNCTION_TABLE (see below). This code deals with an industry standard that uses mnemonics to mean different things and there are hundreds of these mnemonics. So this portion of my code is to decode certain mnemonics pass to it from another section of code that loops through a passed in record... anyway my difficulty is in keeping a member function pointer in a structure outside of the class...
Have a look. I think the code may do a better job explaining ;)
typedef struct _DECODER_FUNCTION_RECS
{
ISO_MNEMONIC_ID Mnemonic;
void (Database::*pFn)(Database::Rec *);
}DECODER_FUNCTION_RECS;
DECODER_FUNCTION_RECS DECODER_FUNCTION_TABLE[] = {
SFP, &Database::Decode_SFP,
KOG, &Database::Decode_KOG
};
void Database::DecodedDescription(Rec *A)
{
int i = 0;
bool Found = false;
while( i < DECODER_FUNCTION_TABLE_COUNT && !Found )
{
if( DECODER_FUNCTION_TABLE[i].Mnemonic == A->Mnemonic )
Found = true;
else
i++;
}
if( Found )
(([DECODER_FUNCTION_TABLE[i]).*this.*pFn)( A );
}
void Database::Decode_SFP(Rec *A)
{
// do decode stuff on A
}
The detail I'm trying to work out is this line:
(([DECODER_FUNCTION_TABLE[i]).*this.*pFn)( A );
You call a member function pointer (that's what it's called) with
(this->*DECODER_FUNCTION_TABLE[i].pFn)(A);
Could put parens around DECODER_FUNCTION_TABLE[i].pFn, but the member access operator . has a higher precedence than member function operator ->*.
I wrote up a few simple examples that will shed some light the other day
It's in my answer to this question
error C2664 and C2597 in OpenGL and DevIL in C++
Or a direct link to codepad