I am trying to implement a Websocket Server. I am using the libwebsockets library.
ConnectionServer.c file has setup code for the library and main() function (I don't see anything of importance to post here.) This file includes 1 file for the received data callback called:
dmserver_callback.cpp.
This file then includes another file (my custom parser file) called:
data_parser.cpp.
This file then includes a file called definitions.h (the source of the problem).
Just bear with me; I understand that including files (daisy chaining; so to speak) probably isn't the best way to do this, and I more than likely should be using header files and such. One question I have is that is this particularly necessary?
To clarify, everything is working as intended until I try to add my own parsing mechanism.
The definitions.h file is as follows:
namespace EngineDefinitions {
enum Version {
Major = 1,
Minor = 2
}; //Version;
namespace Server {
enum enum_Server {
MAX_PLAYERS = 200,
MAX_TABLES = 42, // 3 tables per row.
MAX_TABLE_PLAYERS = 10,
GAME_PORT = 2040, //2042
MAX_PARAMS = 10
}; //Server;
};
namespace Login {
enum enum_Login {
USERNAME = 1,
PASSWORD = 2
}; //Login;
};
};
My error is:
definitions.h(1): error C2061: syntax error : identifier 'EngineDefinitions'
I loaded the exact same header in a new Win32 Console Project in Visual C++ 2010 Express and there it works. The only difference I see is the main file (where int main function resides).
In the project that the header file works is called:
ConectionServer.cpp (C++)
and the main project file that doesn't work is named:
ConnectionServer.c (C)
Does this have something to do with the file being compiled in C vs C++?
I think that the libwebsocket library is coded in C.
I can't recall if I created the project files in exactly the same manner or not.
P.S. Please let me know if there is any other information I can provide to help.
EDIT: I also realize you're not supposed to define types inside a header file (eg: enums).
I DID try to separate the source into .cpp and a header file using the extern enum
with no difference. In fact, got more errors (redefinitions) than I bargained for when trying to use them.
You need to understand that C++ and C are different languages. When you include the header file in a .cpp file, the compiler will try to compile the .h as C++ code. C++ supports namespaces, so everyone is happy. But when you try to include the .h from the .c file (which is what is actually happening if you follow the #includes), the compiler attempts to compile the .h as C code, yet fails because namespaces do not exist in C.
A common way to solve this problem is to use predefined macros. __cplusplus is defined when compiling as C++ code, and not defined when compiling as C code (obviously).
You could do this:
#ifdef __cplusplus
namespace EngineDefinitions {
#endif
enum Version {
Major = 1,
Minor = 2
}; //Version;
#ifdef __cplusplus
namespace Server {
#endif
enum enum_Server {
MAX_PLAYERS = 200,
MAX_TABLES = 42, // 3 tables per row.
MAX_TABLE_PLAYERS = 10,
GAME_PORT = 2040, //2042
MAX_PARAMS = 10
}; //Server;
#ifdef __cplusplus
};
#endif
#ifdef __cplusplus
namespace Login {
#endif
enum enum_Login {
USERNAME = 1,
PASSWORD = 2
}; //Login;
#ifdef __cplusplus
};
#endif
And of course, you lose the ability of namespaces in C anyways.
C does not have namespaces. For Real.
You cannot include a C++ file in a C file (unless it has been prepared for such use). If you then try to compile the C file, it'll try to compile even the C++ file as C. Instead, use separate compilation and header files.
Note that C does not understand namespaces.
Related
this is linked to Redefinition and Enumerator and Reusing enum values in separate enum types and similar issues.
I have a VS2013 project using a header and lib from an external source which I cannot get a new version from.
When I upgrade to v142/VS2019 and compile I get the error "C2365 'PS_DEFAULT': redefinition; previous definition was 'enumerator'" from the external header.
I cannot find the enum PARA_STATE or PS_DEFAULT anywhere else in the code except in the header.
The header code looks like this:
#ifndef GLX_DBMS_H
#define GLX_DBMS_H
...
enum PARA_STATE
{
PS_NDEF,
PS_DEFAULT,
PS_DEFAULT_LONG,
PS_PARAM,
PS_PARAM_LONG,
PS_CONNECTED
};
struct Para
{
DATA_TYPE paraType;
WORD paraTypeLength;
char paraName[SIZEPARANAME];
PARA_STATE strucType;
}
struct ParaV8
{
DATA_TYPE paraType;
WORD paraTypeLength;
char paraName[SIZEPARANAME];
PARA_STATE strucType;
}
...
#endif
What changed between 2013 and 2019 so this no longer works?
Is there a way to fix this outside of getting a new version from the external?
UPDATE
I looked at Messages in Visual studio as suggested and line 3835 in ShObjIdl_core.h has an enum with PS_DEFAULT so that is the cause.
I tried two different "solutions" which both work, but are hacks.
I added class to the enum in the windows header line 3828 and it compiled. This is only a local solution though
enum class PLACEHOLDER_STATES
Change the name in my external header file, I think I will only get away with this since the enum is not used in the rest of the code.
enum PARA_STATE
{
PS_NDEF,
PS__DEFAULT
};
If I see correctly ShObjIdl_core.h is for COM and the external library uses COM so I am not able to get rid of the dependency.
Any better solutions?
In my case
I created typedef enum { ME1 = 0,ME2 }MyEnum; in MDefine.h header file.
And I was trying to use ME1 in CtrlBit.h
And the main problem was
NOT DOING #pragma once in MDefine.h which has MyEnum.
(yeah!! I was sure that it's not possible that my variables declared in other files..)
Also, I include MDefine.h in stdafx.h
And yeah! My problem was solved))
I am trying to use Casablanca, http server. to do so, I need to include headers files from Casablanca, which contains few macro and typedef that cause issues in my project.
so my file look like this.
simplehttpserver.h
#include "cpprest/json.h"
#include "cpprest/http_listener.h"
#include "cpprest/uri.h"
#include "cpprest/asyncrt_utils.h"
SimpleHttpServer {
SimpleHttpServer(utility::string_t, std::function<void(http_request)> &request_handler);
void OnInitialize();
void StartServer();
void StopServer();
private:
std::unique_ptr<http_listener> m_listenerUptr;
// Handlers
std::function<void(http::http_request)> m_all_requests;
pplx::task<void> open() { return m_listenerUptr->open(); }
pplx::task<void> close() { return m_listenerUptr->close(); }
// SimpleHttpServer http_server_;
utility::string_t address_;
}
Say in my original code where I want to include this.
#include "simplehttpserver.h"
this causes all Casablanca header files pre-compiled into my project which conflicts with macros and typedef in my project.
e.g. __declspec
I don't want to change my macros cause that will be lot of code change. and I don't want to change Casablanca header files, cause that will also cause long term maintenance overhead.
I am sure, this must be very common problem in c++, can someone please help me how can resolve this.
thanks in advance.
The Situation
I am writing a wrapper library for GPIB communications for setting up specific instruments according to a clients specifications to automate some of their processes. I have to use C++ and the old '98 compiler in VC++ 6.0 running on a Windows NT machine to maintain compatibility with some other devices they use regularly.
I am trying to make a class that combines some GPIB commands into easier to remember functions, while also keeping the capability of directly communicating with the instruments. To that end, I have compiled different parts of my project into different libs and dlls, each dll being a different device that they might want to communicate with. I also made a generic dll base class from which all the specific instrument classes inherit, hopefully making the whole setup as modular as possible.
The Problem
So, with all that said, I have an issue when I try to test the different dlls/modules. I created a project to test the generic base class, added the .lib file to the project, which links to the .dll, and also #included the header file for that dll. testGeneric.cpp looks like this:
#include "GENERIC.h"
void main(void) {
GPIBInstrument hp(2); //connects to device at primary address #2
hp.write("*IDN?");
}
Super simple. To be clear, I also have the GENERIC.lib linked in the "Resource Files" folder in VC++ 6.0, and I have GENERIC.dll accessible from the path variable.
Moving on, GENERIC.h looks like this (select parts):
#ifndef GENERIC_H
#define GENERIC_H
#include <string>
#include <windows.h>
#include "decl-32.h"
#ifdef GENERIC_EXPORT
#define GENERIC_API __declspec(dllexport)
#else
#define GENERIC_API __declspec(dllimport)
#endif
...(Inline exception classes)...
class GENERIC_API GPIBInstrument {
...
public:
void write(std::string command);
...
};
#endif
Just showing the relevant methods. Then GENERIC.cpp:
#define GENERIC_EXPORT
#include "GENERIC.h"
...
void GPIBInstrument::write(std::string command) {
ibwrt (handle, &command[0u], command.length());
std::cout << command << std::endl;
if (ibsta & TIMO) {
timeoutError();
}
if (ibsta & ERR) {
error("Unable to write command to instrument: " + command);
}
}
So, looks pretty good right? No issues. Compiles fine. I try running it, and BLAM! I get this: "User breakpoint called from code at 0x77f7645c". So, then I thought, well maybe it would work if I put all the code from GENERIC.h and GENERIC.cpp into one file, and #included that file all as inline code. So I tried it, and it and it compiled nicely, and ran fine.
Question (<-AHA!... But...)
What am I doing wrong!? Something with the way I'm making the .dll? Or the .lib? Or something else entirely?
EDIT (WHY!?)
So, after a bit of debugging, I found that it was something to do with passing a string literal. So I just modified it to:
std::string command = "*IDN?";
hp.write(command);
and it worked fine. My followup question, is why? What's the difference between having a string literal passed, versus assigning that to a variable and then passing it in?
Using complex types such as std::string as a parameter at a DLL boundary is tricky. You must ensure that the exe and the DLL use the exact same instance of the library code. This requires that you build them both to use the same version of the DLL version of the runtime library.
i am at wit's end trying to make SWI-Prolog play nice with C++. Now, before i start explaining exactly what my problem is, i want to first state what my project is about and what tools i chose in order to develop a solution.
My professor assigned to me the task of developing a GUI program that serves as a frontend to SWI-prolog, and this frontend is to be developed in C++. I chose to use Qt to design the GUI and use C++ as a backend to bridge SWI-Prolog to the application. The user of this application should be able to input some lists and then choose operations to be applied to them through prolog, like if, for example, I input a list of numbers, then by click of a button the user gets another list of all the numbers that are pairs in this list (if there are any). I am developing on a unix OS, more specifically, netrunner rolling release, based on archlinux and manjaro.
I did some research, and it seemed that the best course of action in order to interface SWI-Prolog (may i also mention that my professor also recommended this), is to use the header and source file developed by Volker Wysk; for reference, here is the link to the compressed file that contains these files http://www.volker-wysk.de/swiprolog-c++/index.html
Now here is my problem: if you visited the page i just gave you you will see that this C++ implementation of the SWI-Prolog interface is quite old: last time it was worked on was in the year 2002. I had to modify the header file so that i could get rid of some of the errors, like putting using namespace std or changing #include ostream.h to #include ostream, and so i managed to get the error count to only two which i can't manage to fix and which i think i won't be able to because there are two functions whose implementation i can't find anywhere: the function is declared but the code that it is supposed to run when they are called can't be found.
I will now list the contents of the files i consider to be most relevant. I have the latest version of SWI-Prolog installed, and so the SWI-Prolog.h header is the latest one that comes with the installation of the newest prolog (version 6.6.5).
#-------------------------------------------------
#
# Project created by QtCreator 2014-07-05T12:38:45
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = prologFrontend
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
../../../../../../../../usr/local/share/swiprolog-c++/prolog.cpp
LIBS += -L/usr/lib/swipl-6.6.5/lib/x86_64-linux -lswipl
HEADERS += mainwindow.h
FORMS += mainwindow.ui
contents of the prologFrontend.pro file (Qt creator project file)
#include "mainwindow.h"
#include <QApplication>
#include <prolog.hpp>
int main(int argc, char *argv[])
{
try {
Prolog_impl::prolog_init(argc, argv);
} catch(Prolog_impl::PlError &error) {
}
QApplication prog(argc, argv);
MainWindow w;
w.show();
return prog.exec();
}
contents of the main.cpp file
I would copy the whole contents of the header and source files made by Volker Wysk, but it's too long to fit in here. You can take a look at them if you download it from the link to his site i already posted. Next are the errors i am getting and the two corresponding code snippets where they happen in the .cpp file that he made:
// part of SWI-Prolog, but not exportet by header file
// /usr/local/src/swiprolog-4.0.9/src/pl-funcs.h
//NOTE: this function is declared here but it's even not to be found in the header file
//prolog.hpp. Its implementation can't be found anywhere using the function definition
//navigation capability of Qt so, basically, its a function that does nothing.
extern "C"{
unsigned long pl_atom_to_term(term_t in_atom,
term_t out_term,
term_t out_bindings);
}
bool Prolog_impl::atom_to_term(const char* text, Term* t, list<Term::Binding>* b)
{
Term in_atom = Atom(text);
Term out_term;
Term out_bindings;
if (!pl_atom_to_term(in_atom.lsi, out_term.lsi, out_bindings.lsi))
return false;
if (t) *t = out_term;
if (b) *b = out_bindings;
return true;
}
And the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:45: error: undefined reference to `pl_atom_to_term'.
//Note that this code has the same issues as the one above: no implementation to be found
extern "C"{
unsigned long pl_copy_term(term_t in, term_t out);
}
Term Prolog_impl::copy_term(Term t)
{
term_t t2 = PL_new_term_ref();
if (!pl_copy_term(t.lsi, t2))
throw LogicError("copy_term(Term)", "failure calling pl_copy_term()");
return Term(t2);
}
and the error that this code throws: /usr/local/share/swiprolog-c++/prolog.cpp:60: error: undefined reference to `pl_copy_term'.
Aside from the changes I had to make to the header file I already mentioned, I had to fix this line of code in the header file:
#include <SWI-Prolog.h>
to this:
#include "/usr/lib/swipl-6.6.5/include/SWI-Prolog.h"
This is because, otherwise, the compiler complains that it can't find that header file.
My guess is that these functions used to exist in an older SWI-Prolog version. I have no real clue about what to do with this task, i tried reading up on other alternatives to using volker's implementation but it's like there is close to none good information on the net about how to interface Prolog with C++.
Thank you so very much for taking your time to read my question. If you have a solution that works, please let me know. It doesn't have to be SWI-Prolog, it could be any other Prolog environment that interfaces nicely with C++ and that uses more or less about the same syntax that SWI-Prolog uses, though i think that the syntax is already standard for all environments.
Package swipl-win is a working SWI-Prolog / Qt interface, portable on Linux,MacOS,Windows. I have many others here, but these are restricted to running on Linux by now...
I wonder why, apart Qt specific problems, have you chosen an old, unmaintained C++ interface, when there is an 'official' one here. This interface is working pretty well, giving parameter validation based on exception handling and automatic type conversion. Then it's easy to add to the interface - for instance, from PREDICATE.h
typedef PlTerm T;
#define LOOP__ { } operator bool() { return next_solution(); }
#define query0(P) struct P : PlQuery { P() : PlQuery(#P, V()) LOOP__ };
#define query1(P) struct P : PlQuery { P(T A) : PlQuery(#P, V(A)) LOOP__ };
...
allows
query1(current_predicate)
void Completion::initialize(QSet<QString> &strings, bool reload) {
Q_UNUSED(reload)
T PRED;
for (current_predicate cp(PRED); cp; ) {
QString p = t2w(PRED);
if (p[0].isLetter())
strings.insert(p);
}
qDebug() << "Completion::initialize loaded" << strings.count();
}
About your specific problems, probably those functions are obsolete, you should stick to C Api (also know as foreign language interface) documented here.
Looking into the Makefile for swiprolog-c++-0.1.0, it looks like a special linker needs to be used, called plld. So you need to use your usual compiler to generate only the object files, then use that linker to create the executable.
The plld line in the makefile looks like this:
main : main.o prolog.o test.pl
plld -o $# -ld $(CC) $^ -lstdc++
The "recipe" line expands to this:
plld -o main -ld gcc main.o prolog.o test.pl -lstdc++
I am doing my first steps in IPhone developing. I want to use some c\c++ code but I can't find any reference of how it's done (will very appriciate if you can also refer me to your source when you give an answear)
I have a file called calc.h containing a "calculator" class with simple add and mult functions, I imported it exactly as I did with an Objective-C header file. What am I suppose to do now?
Whatever you were doing when you were coding just in C/C++.
For example:
#include "calc.h"
....
-(void) testCode { //obj-c
float x = 3;
float y = 8.0;
float sumOfTwo = sum(x, y);
}
Assuming that you have a function named sum in your header file similar with the one used above.
If you use standard extensions for the source files (e.g. .cpp / .c) you can simply build them without doing anything special.
If you use uncommon extensions you need to set the file type manually: In File → Get Info set File Type to sourcecode.cpp.cpp / sourcecode.c.c.
Note however that you can't use C++ in plain Objective-C (.m) files - if you want to do that you need to use Objective-C++ (.mm) instead.
For using C there is no such restriction as Objective-C is a superset of C - as with C++ you may need to watch out for uses of identifiers that are keywords in Objective-C though.