I have these three source files:
test.h
#ifndef __TESTH
#define __TESTH
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef struct {
uint8_t value;
} my_struct;
EXTERNC void initialise();
EXTERNC void load(my_struct**);
#endif
test.cpp:
#include <cstdint>
#include "test.h"
my_struct test;
void initialise() {
test.value = 200;
}
void load(my_struct** struct_ptr) {
*struct_ptr = &test;
}
main.cpp:
#include <cstdint>
#include <iostream>
#include "test.h"
my_struct *test;
int main() {
initialise();
load(&test);
while (true) {
std::cout << test->value << std::endl;
}
}
When I compile it, the linker gives me an error telling me that test has been defined multiple times (first defined in test.cpp).
Why? To me it seems like it doesn't leave the scope of test.cpp.
And when I remove the definition of test in main.cpp, it gives me an undefined error!
Thank you for taking the time out of your day to help me.
I think you would need to scope test.cpp's test variable to that file only, assuming your test pointer in main.cpp is different than test in test.cpp
namespace {
my_struct test;
}
See here
I am experimenting with cgo, and wanted to use c++ with cgo. I found this post about doing it. If I have a c++ struct named Foo and a go struct named Foo, I want to pass the go Foo to c++. I tried doing this:
//bind.h
#ifdef __cplusplus
extern "C" {
#endif
#include "structs.hpp"
void bindCgo(Foo bar);
#ifdef __cplusplus
}
#endif
//structs.hpp
#ifndef STRUCTS_HPP_
#define STRUCTS_HPP_
typedef struct Foo {
#ifdef __cplusplus
std::string str;
#endif
}
#endif
//bind.cc
#include "structs.hpp"
using namespace std;
void bindCgo(Foo bar) {
cout << bar.str << endl; //this gives "sΘ\"
}
//main.go
import "unsafe"
// #cgo CFLAGS: -std=c99
// #include "bind.h"
import "C"
type Foo struct {
str string
}
func main() {
bar := Foo{""};
C.bindCgo(((*C.Foo)(unsafe.Pointer(&bar))))
}
Now when I run this program, it gives me sΘ\. Is this normal, and how can I fix this?
I also have maps and vectors in my struct so using char* will not work
We have defined some methods to allow for ad-hoc console input when required. The methods are contained within a namespace and define and use a class to perform the actual work.
The definions, stripped down for brevity:
ConsoleInput.h
#include <cstddef>
#include <map>
#include <memory>
#include <vector>
namespace MyNameSpc
{
typedef std::vector<char> buffer_t;
class ConsoleInput
{
// Methods for windows and linux console input
}
int GetString(buffer_t &buffer, ...);
}
RequestInput.h
#include "ConsoleInput.h"
#include <cstddef>
#include <string>
namespace MyNameSpc
{
const std::string empty = std::string();
class RequestInputParam
{
// Methods
}
int RequestInput(buffer_t &buffer);
int RequestInput(buffer_t &buffer, const RequestInputParam ¶m);
// and other overloads
}
ConsoleInput.cpp
#include "ConsoleInput.h"
#include "RequestInput.h"
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <fcntl.h>
#include <stdio.h>
// and other headers.
namespace MyNameSpc
{
// implements class ConsoleInput methods.
// Implements GetString()
}
RequestInput.cpp
#include "ConsoleInput.h"
#include "RequestInput.h"
#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
namespace MyNameSpc
{
// implements the overloaded methods.
}
And we call them by #include RequestInput.h and then calling int retVal = MyNameSpc::RequestInput(...). This all works fine when all of the code is C++. I now have to reference this code from C code which was recently dropped into our repository. I don't think I can (well, I -can-, but I think it's going to break other things) simply compile the C code as C++, so I really do need to somehow pull this into C.
When I tried to build, I was getting initial errors about not finding the iostream header.. makes sense, but, after reading about extern "C", I am unclear how to proceed, when I have these C++ headers in the code, classes (the only one I might need to reference is the parameter class) and namespaces.
UPDATE
I have reviewed the links which were provided and attempted to make use of the information from here and here. I am having no success with this.
RequestInputWrapper.h
#ifndef REQUEST_WRAPPER_H
#define REQUEST_WRAPPER_H
#include <stddef.h>
#include "RequestInput.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct RequestInputParam RequestInputParam; // line 29
RequestInputParam* CreateRequestInputParam();
void DisposeRequestInputParam( RequestInputParam* pObject );
void C_AddMainPrompt(RequestInputParam *param, char *msg);
int C_RequestInputAllocPtr(char * * const ppInput,
unsigned int * const pInputLen);
int C_RequestInput(char * const pInput,
unsigned int * const pInputLen);
#ifdef __cplusplus
}
#endif
#endif /* REQUEST_WRAPPER_H */
RequestInputWrapper.cpp
#include "RequestInput.h"
#include "RequestInputWrapper.h" // line 13
#ifdef __cplusplus
extern "C" {
#endif
RequestInputParam* CreateRequestInputParam()
{
return new RequestInputParam(); // line 25
}
void DisposeRequestInputParam( RequestInputParam* pObject ) // line 28
{
if ( pObject != NULL )
{
delete pObject; // line 32
pObject = NULL;
}
}
void C_AddMainPrompt(RequestInputParam *param, char *msg) { param->AddMainPrompt( msg ); }
int C_RequestInputAllocPtr(char * * const ppInput,
unsigned int * const pInputLen)
{
return RequestInput(ppInput, pInputLen);
}
int C_RequestInput(char * const pInput,
unsigned int * const pInputLen)
{
return RequestInput(pInput, pInputLen);
}
#ifdef __cplusplus
}
#endif
It is currently throwing the following errors (I C&P only the first portion, it started getting repetitive; the line numbers won't match the code above, which has been stripped of all comments and such so I added comments with the noted line #'s):
cli/RequestInputWrapper.cpp: In function ‘RequestInputParam* CreateRequestInputParam()’:
cli/RequestInputWrapper.cpp:25:35: error: invalid use of incomplete type ‘RequestInputParam {aka struct RequestInputParam}’
return new RequestInputParam();
^
In file included from cli/RequestInputWrapper.cpp:13:0:
./Include/RequestInputWrapper.h:29:16: error: forward declaration of ‘RequestInputParam {aka struct RequestInputParam}’
typedef struct RequestInputParam RequestInputParam;
^
cli/RequestInputWrapper.cpp: In function ‘void DisposeRequestInputParam(RequestInputParam*)’:
cli/RequestInputWrapper.cpp:32:16: error: possible problem detected in invocation of delete operator: [-Werror]
delete pObject;
^
cli/RequestInputWrapper.cpp:28:6: error: ‘pObject’ has incomplete type [-Werror]
void DisposeRequestInputParam( RequestInputParam* pObject )
^
In file included from cli/RequestInputWrapper.cpp:13:0:
./Include/RequestInputWrapper.h:29:16: error: forward declaration of ‘struct RequestInputParam’ [-Werror]
typedef struct RequestInputParam RequestInputParam;
^
cli/RequestInputWrapper.cpp:32:16: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
delete pObject;
^
I suspect the answers in the articles suggested as "duplicates" have simply been written and not tested. After more searching, I eventually stumbled across this answer which offered the guidance needed to get this to build.
In short, I was missing the namespace in my C++ wrapper code (facepalm) and I had to add the reinterpret_cast calls. I also changed the name of the type in the typedef... I thought it was referencing the C++ type (as that was what at least one example seemed to show) but, nope... it needs to be it's own struct type.
RequestInputWrapper.h
#ifndef REQUEST_WRAPPER_H
#define REQUEST_WRAPPER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
typedef struct C_RequestInputParam C_RequestInputParam;
C_RequestInputParam * CreateRequestInputParam();
void DisposeRequestInputParam( C_RequestInputParam *pObject );
void C_AddMainPrompt( C_RequestInputParam *param, char *msg);
int C_RequestInputAllocPtr( char * * const ppInput,
unsigned int * const pInputLen );
int C_RequestInput( char * const pInput,
unsigned int * const pInputLen );
#ifdef __cplusplus
}
#endif
#endif /* REQUEST_WRAPPER_H */
RequestInputWrapper.cpp
#include "RequestInput.h"
#include "RequestInputWrapper.h"
extern "C" {
C_RequestInputParam * CreateRequestInputParam()
{
return reinterpret_cast< C_RequestInputParam * >( new RequestInputParam() );
}
void DisposeRequestInputParam( C_RequestInputParam *pObject )
{
if ( pObject != NULL )
{
delete reinterpret_cast< MyNameSpc::RequestInputParam * >( pObject );
pObject = NULL;
}
}
void C_AddMainPrompt( C_RequestInputParam *param, char *msg )
{
reinterpret_cast< MyNameSpc::RequestInputParam * >( param )->AddMainPrompt( msg );
}
int C_RequestInputAllocPtr( char * * const ppInput,
unsigned int * const pInputLen )
{
return MyNameSpc::RequestInput( ppInput, pInputLen );
}
int C_RequestInput( char * const pInput,
unsigned int * const pInputLen )
{
return MyNameSpc::RequestInput( pInput, pInputLen );
}
}
I am dealing with a dll project for my internship. I have to write a C++ code including some basic functions for pl/sql with dev c compiler and it must be work as a pl/sql tool.I wrote this codes.And i save the source file as dll file.I copied the dll extension file to plugin directory of pl/sql developer.It did not work.
Thank you all.
Here is my header and source code.
// header file plsqlHx.h
#ifndef _DLL_H_
#define _DLL_H_
#define DLL_EX
#include <string>
using namespace std;
extern "C" __declspec (dllexport) DLL_EX const char* IdentifyPlugIn(int);
extern "C" __declspec (dllexport) DLL_EX const char* CreateMenuItem(int);
extern "C" __declspec(dllexport) DLL_EX void OnMenuClick(int);
#endif
#include "plsqlHx.h"
#include <iostream>
#include <windows.h>
#include <string>
const char *const Desc = "C++Builder Plug-In demo 1";
int PlugInID;
const char* IdentifyPlugIn(int ID){
PlugInID = ID;
return Desc;
}
const char* CreateMenuItem(int Index){
switch (Index)
{
case 1 : return "Tools / &Plug-In 1 Demo...";
}
return "";
}
void OnMenuClick (int Index){
switch(Index){
case 11:
cout << "Hello";
break;
case 12:
cout << "Goodbye";
break;
}
}
I have a header file and its cpp file (Error.h, Error.cpp). The cpp file performs a check on a preprocessor directive but it always fails.
Error.h:
/*
Optional macros:
AE_EXIT_AT_ERROR
AE_CONSOLE_WRITE_AT_ERROR
*/
#pragma once
extern void aeError(const char *str, int code=1);
extern void aeAssert(bool b, const char *failStr = "assertion failed");
Error.cpp:
#include "Error.h"
#include <stdexcept>
#ifdef AE_CONSOLE_WRITE_AT_ERROR
#include <iostream>
#endif
void aeError(const char *str, int code)
{
#ifdef AE_CONSOLE_WRITE_AT_ERROR
std::cout << str << std::endl;
#endif
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr)
{
if(!b)
aeError(failStr);
}
main.cpp:
//define both macros:
#define AE_CONSOLE_WRITE_AT_ERROR
#define AE_EXIT_AT_ERROR
#include "Error.h"
//rest of code
//...
both std::cout << str << std::endl; and std::exit(code); don't get compiled (I checked it "manually", although they are also marked gray by the IDE, which is VS2010).
What might be the cause of this?
main.cpp and Error.cpp are different translation units. You define the macro only for main.cpp, not for Error.cpp.
You should either put your #define directives in a header file included by both .cpp files, or define these macros in project settings/makefile.