I Currently have a C win32 application in place, I am wanting to make a GUI to communicate and call various api command in my application. In visual studio I select project -> add new items -> [C++ -> windows form] and a nice form pops up. My question is how do I make calls from the form.h file produced. A nice example to see would be seeing a gui modifying a value and that value simply printing out in the console (a function in the application external from the form.h file). If not, any links related would be nice
Thanks!
Define header file for your C library with C++ guards.
#ifdef __cplusplus
extern "C" {
#endif
int my_c_function1(void);
int my_c_function2(void);
struct my_c_struct { ... };
void my_c_function3(struct my_c_struct *p);
...
#ifdef __cplusplus
}
#endif
It is important that all type and function declarations are between #ifdef blocks.
Those blocks tell C++ compiler that the data types and functions from that scope belong to C language and require C ABI bindings.
So you would be able to use those types and functions without error in both C and C++ source files.
Related
I am currently attempting to integrate the AzureStorageCPP into Unreal Engine 4 by using this documentation page. What I am doing is to create a custom C++ DLL wrapper around AzureStorageCPP, and then have Unreal Link this DLL in Unreal Code.
I installed the AzureStorageCPP as DLLs, via vcpkg. On completion, wastorage.dll is one of the important DLLs that needs to be linked.
The C++ DLL wrapper I wrote around AzureStorageCPP is below:
#include "was/storage_account.h"
#include "was/blob.h"
void UploadFileToAzure(char* FileName)
{
azure::storage::cloud_storage_account storage_account = azure::storage::cloud_storage_account::parse(U("DefaultEndpointsProtocol=https;AccountName=test;AccountKey=test"));
}
As far as I can tell, azure::storage::cloud_storage_account::parse lives in wastorage.dll
The issue is that when this parsing code is executed as a C++ Console, it runs just fine. The ConnectionString is passed correctly down the callstack to wastorage.dll, and the connection string is not garbage.
Here is the view one level down the callstack from the code above.
However, if I put the code into the C++ wrapper DLL I made called AzureStorage.DLL, link it into Unreal, and call from there, with the same call stack the string becomes garbage when it gets passed into wastorage.dll to parse.
I thought this might be related to this issue, but I still don't understand how to fix this, as I don't control the Parse method that is from AzureStorage.
Here is how I created the C++ DLL wrapper header, the source is already shown above:
AzureStorage.h
#pragma once
#define AZURESTORAGEDLL_API _declspec(dllexport)
#ifdef __cplusplus //if C++ is used convert it to C to prevent C++'s name mangling of method names
extern "C"
{
#endif
void AZURESTORAGEDLL_API UploadFileToAzure(char* FileName);
#ifdef __cplusplus
}
#endif
I'm trying to include mongoose web server, which is written in C, and write the rest of the code in C++.
When compiling I get the error: redeclaration of C++ built-in type 'bool' in the mongoose header file in Code Blocks
#include <iostream>
#include "mongoose.h"
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}
I enclosed the mongoose header in
#ifdef __cplusplus
extern "C"{
#endif
// header content
#ifdef __cplusplus
}
#endif
and I'm still getting the same error, at #include winsock2.h
C and C++ are different languages that share a common subset. You can compile most C declarations with a C++ compiler by putting them in a section specifying C linkage, as you show, but that follows from the sublanguage of C declarations being almost entirely within the shared subset of C and C++.
C++ has both more declarational features and more constraints than C does, however. In particular, the fact that it provides bool as a built-in type places a constraint that that identifier cannot be redeclared as a typedef name. C, on the other hand, has a standard header that defines exactly such a typedef, and it is not so uncommon for people to roll their own, too. Such typedefs will be rejected by a C++ compiler, C linkage notwithstanding.
If the C project is not already built with a mind toward providing for use by C++ programs, and simply wrapping the header inclusion in a C linkage block does not suffice, then you simply cannot use that library's header as-is. Your options are either to modify it or to provide an alternative. You might even need to provide a few wrapper functions, written in C, to serve as an interface with your C++ program. Details depend on the library you're trying to use.
If this is your only issue, then you could add #define bool C_INT_BOOL near your extern "C", then #undef bool near the }
In your cpp file I would write:
extern "C"{
#define bool C_INT_BOOL
#include "mongoose.h"
#undef bool
}
This allows the "C" interface to see the int parameter type, but shouldn't interfere with your c++ use of bool.
But I doubt this will be your only issue, in which case you will probaby quickly realise that adding an interface function layer is the safest way to go.
I have code written in C only. The main function is main.c, and it include other c files like #include "Flash.h".
I would like to keep the project working but to be able to add a cpp file .
I was told that I have to change the main to be
main.cpp
which will produce 250 errors on compilation- regarding the included c files
What's the proper way to turn the main file to cpp and still include C files ?
main.cpp :
#include "Flash.h"
int main(void)
{
....
}
I have read How to use C source files in a C++ project? which did not provide me a direct solution to the problem (my compiler will use c++ anyway).
EDIT:
Before someone will kill me for asking (don't know why you are so aggressive), I get only 3 kinds of errors 250 times :
'->' cannot appear in a constant-expression
'&' cannot appear in a constant-expression
a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
EDIT 2 :
Here are some of the lines ( running using SDK for some RF chip ):
Most of the errors are from this section
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_GPIOTE_TASKS_OUT_0 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0.*/
NRF_GPIOTE_TASKS_OUT_1 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1.*/
NRF_GPIOTE_TASKS_OUT_2 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2.*/
NRF_GPIOTE_TASKS_OUT_3 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3.*/
#if (GPIOTE_CH_NUM > 4) || defined(__SDK_DOXYGEN__)
NRF_GPIOTE_TASKS_OUT_4 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4.*/
NRF_GPIOTE_TASKS_OUT_5 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5.*/
NRF_GPIOTE_TASKS_OUT_6 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6.*/
NRF_GPIOTE_TASKS_OUT_7 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7.*/
On these lines the same error repeat :
a cast to a type other than an integral or enumeration type cannot appear in a constant-expression
The #include directive in C++ is a literal inclusion of source code. Imagine your C source code in Flash.h included by main.c doing something incompatible with C++ like
typedef int class;
Now, in your main.cpp you have
#include "Flash.h"
It's exactly as if you had this code typedef int class; directly in your C++ source file - so it's an error.
If you have C source code with C headers, you don't need to use C++ at all!
If you want to write new C++ code and make it call old code (or vice-versa), just use the linker. Have C++ code include C++ headers, and separately, C code include C headers, and the linker will combine all your code into an executable.
To make your C and C++ parts work together, you need an additional header file. For example call it c-cpp-interface.h. Then include it in all your C and C++ source files:
#include "c-cpp-interface.h" // in C files
extern "C" {
#include "c-cpp-interface.h" // in C++ files
}
This file should be written in a common C/C++ subset language. That is, mostly, C language but with increased type safety (e.g. prototypes for all functions must be written fully, without the implied ... arguments).
Ideally, your existing C header file could be used as such. However, C header files often accumulate cruft, and it might be more practical to create a new file than clean the existing one(s).
Looking at the actual error messages you have (with offsetof), you should try to have as little code as possible in the C - C++ interface. Don't put implementation details (like values of various constants) there. Only have there the declarations/prototypes for functions that are called by the other language (C calling C++ or vice versa).
The question you post points out you need to wrap the inclues
extern "C" {
#include "cheader.h"
}
In your case,
extern "C" {
#include "Flash.h"
}
int main(void)
{
}
and in each cpp that wants to use C code, use extern "C" round the include.
I have a C++ project that I have configured using Cmake to use Eclipse. My problem is that I have added a static C library (namely, svm-struct/svm-light) which doesn't seem to compile- and my guess is that it's compiling as C++ instead of C.
I added the library to my project as follows:
SET(SVM_LIGHT_SRC_DIR "../../Libraries/svm_rank")
INCLUDE_DIRECTORIES(${SVM_LIGHT_SRC_DIR})
ADD_LIBRARY(
svm_rank_lib STATIC
${SVM_LIGHT_SRC_DIR}/svm_light/svm_learn.c
${SVM_LIGHT_SRC_DIR}/svm_light/svm_common.c
${SVM_LIGHT_SRC_DIR}/svm_light/svm_hideo.c
${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_learn.c
${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_common.c
${SVM_LIGHT_SRC_DIR}/svm_struct/svm_struct_classify.c
${SVM_LIGHT_SRC_DIR}/svm_struct_api.c
${SVM_LIGHT_SRC_DIR}/svm_struct_learn_custom.c
)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} svm_rank_lib)
Cmake configures fine it seems. Within the output of the configuration it specifies that it finds my C and C++ compilers and that they "work". I add the header to one of my project files using extern as follows:
#ifdef __cplusplus
extern "C" {
# include "svm_struct/svm_struct_common.h"
}
#endif
When I go to build my project the error is here:
../../Libraries/svm_rank/svm_struct/../svm_struct_api_types.h:75:11: error: expected member name or ';' after declaration specifiers
double *class; /* vector of scores that imply ranking */
~~~~~~ ^
1 error generated.
There is a variable within the library header called "class" where the error occurs, and my guess is that it's trying to compile this library header using C++ instead of C. First of all is this the reason for the error? If so, how should I go about fixing this?
As has already been pointed out, the source of the problem is that the C library header declares a variable named class, which is a keyword in C++.
This problem will hit you as soon as that header is pulled in by a C++ source file. Remember that headers are not compiled by themselves, but are merely copy-pasted by the preprocessor into the source file that #includes them. It is the type of the source file that determines whether the code in the header is interpreted as C or C++.
The fact that you wrapped the include in extern "C" does not change this. It simply switches off C++-style name mangling for the declarations in the header, but the code still has to compile as valid C++.
The cleanest solution to this problem is a technique known as insulation or compiler firewall.
You have to make sure that all parts that come into contact with the problematic library are C-source files themselves. The C++ part of your code only interacts with the library through the interface of that C part, but never with the library directly. In particular, you must never #include library headers from any of your header files.
For instance:
my_interface.c
#include "svm_struct/svm_struct_common.h" /* safe to include from a .c file */
struct opaque_ {
/* you can use types from svm_struct_common in here */
};
opaque* initialize()
{
/* you can create an opaque_ on the heap and
manipulate it here, as well as give a
pointer back to the C++ part */
}
void do_stuff(opaque*)
{
/* do whatever you like with the stuff in opaque */
}
my_interface.h
/* no #includes in the header! */
/* the opaque type is only forward declared!
C++ code can obtain a pointer to it,
but cannot look inside */
struct opaque_;
typedef struct opaque_ opaque;
opaque* initialize();
void do_stuff(opaque*);
my_application.cpp
// we only include our own header, which we made sure is valid C++
extern "C" {
#include <my_interface.h>
}
void do_stuff()
{
opaque* context = initialize();
do_stuff(context);
}
double *class; /* vector of scores that imply ranking */
class as highlighted in blue if it helps. Is a reserved word meaning you can't use it as a variable or macro name. Try changing it and it should remove the error.
Edit
I misunderstood you are compiling in C but it seems to compile in C++. But I still stand by my answer its best to change the variable class to keep the code compatible with C++ as class is a reserved word in C++.
I am trying to use digital scope Vellman PCSU1000 in one of my projects which I am writing in C++ in Visual Studio 2010.
In order to do this I need to use two DLLs provided by the producer of the device: DSOLink.dll and PCSU1000D.dll. I do not have any other associated files. As far as I understood from the manual those DLLs were writen and compiled in Deplhi. There is a short description of the functions contained in each of DLL and how to use them in different programming languages. For C++ language producer chose Borland C++ Builder and added following code (for using DSOLink.dll, it is analogous for PCSU1000D.dll):
DSOLink.h
//---------------------------------------------------------------------------
// DSOLink.h
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif
#define FUNCTION __declspec(dllimport)
FUNCTION bool __stdcall DataReady(); /*this particular line is added by me based on
list of the functions listed by dumpbin/exports DSOlink.dll and manual*/
FUNCTION __stdcall ReadCh1(int* ptr);
FUNCTION __stdcall ReadCh2(int* ptr);
#ifdef __cplusplus
}
#endif
//---------------------------------------------------------------------------
According to instruction found in MSDN: http://support.microsoft.com/kb/131313
I have created a .lib file. Thanks to that the Build Solution finishes succesfully but Debugging returns error message "Cannot find the entry point of function _DataReady#0 in DSOLink.dll".
From the article: http://bcbjournal.org/articles/vol4/0012/Using_Visual_C_DLLs_with_CBuilder.htm?PHPSESSID=ab5f6c83b3da921591a490a5accb5bf7 I know that in C++ Builder the keyword *__stdcall* indicates no decoration convetion while in VS means exactly opposite.
I understand that in this situation I am forced to use *__stdcall* in VS (it has to be the same method of managing stack cleaning in DLL and in header used in aplication) and no-decoration method at the same time...I have read that .DEF files may help but I am lost how exactly it should be used. I was trying to create DEF in different ways:
EXPORTS
DataRead=DataRead
.
.
.
EXPORTS
DataRead=_DataRead#0
.
.
.
EXPORTS
_DataRead#0=DataRead
.
.
.
and added one of them at once to my project but none of them solves the problem.
Does anybody have an idea what is the proper way of forcing VS not to use and not to expect decorated names with *__stdcall*?
Or maybe reason of my problem is something different and somebody knows it?
Thanks in advance.