#include <netlink/socket.h>
#include <netlink/netlink.h>
struct nl_sock *sock;
sock = nl_socket_alloc();
The above code always fails to compile with the following error:
/home/micah/Documents/C++/Socket_fun/Socket_fun/src/main.cpp|5|error: ‘sock’ does not name a type
I got this from the libnl example, and as it doesn't work, I am wondering, what is the correct way to do this?
That code has to be in a function, you can't just start calling functions outside the context of a function:
int main()
{
struct nl_sock *sock;
sock = nl_socket_alloc();
}
Also, what are you compiling with? I would recommend compiling it as C, not C++.
Related
Overview
I am trying to develop a C++ application which allows for user-created plugins.
I found a nice library called Pluma (http://pluma-framework.sourceforge.net/) which functionally seems to be exactly what I want.
After going through their tutorial, I was able to (with a bit of difficulty) convince the plugin to compile. However, it refuses to play nice and connect with the main program; returning various errors depending on how I try to implement them.
Problem
If I comment out the line labeled 'Main problem line' (in the last file, main.cpp), the plugin compiles successfully, and the main app can recognize it, but it says that "Nothing registered by plugin 'libRNCypher'", and none of the functions can be called.
If I compile that line, the main application instead says "Failed to load library 'Plugins/libRNCypher.so'. OS returned error: 'Plugins/libRNCypher.so: undefined symbol: _ZTIN5pluma8ProviderE".
My guess is that it has something to do with the way the plugin was compiled, as compiling it initially did not work and Code::Blocks told me to compile with "-fPIC" as a flag (doing so made it compile).
Code
Code below:
Main.cpp
#include "Pluma/Pluma.hpp"
#include "CryptoBase.h"
int main()
{
pluma::Pluma manager;
manager.acceptProviderType< CryptoBaseProvider >();
manager.loadFromFolder("Plugins", true);
std::vector<CryptoBaseProvider*> providers;
manager.getProviders(providers);
return 0;
}
CryptoBase.h
#ifndef CRYPTOBASE_H_INCLUDED
#define CRYPTOBASE_H_INCLUDED
#include "Pluma/Pluma.hpp"
#include <string>
#include <vector>
#include <bitset>
//Base class from which all crypto plug-ins will derive
class CryptoBase
{
public:
CryptoBase();
~CryptoBase();
virtual std::string GetCypherName() const = 0;
virtual std::vector<std::string> GetCryptoRecApps() const = 0;
virtual void HandleData(std::vector< std::bitset<8> > _data) const = 0;
};
PLUMA_PROVIDER_HEADER(CryptoBase)
#endif // CRYPTOBASE_H_INCLUDED
RNCypher.h (This is part of the plugin)
#ifndef RNCYPHER_H_INCLUDED
#define RNCYPHER_H_INCLUDED
#include <string>
#include <vector>
#include <bitset>
#include "../Encoder/Pluma/Pluma.hpp"
#include "../Encoder/CryptoBase.h"
class RNCypher : public CryptoBase
{
public:
std::string GetCypherName() const
{
return "RNCypher";
}
std::vector<std::string> GetCryptoRecApps() const
{
std::vector<std::string> vec;
vec.push_back("Storage");
return vec;
}
void HandleData(std::vector< std::bitset<8> > _data) const
{
char letter = 'v';
_data.clear();
_data.push_back(std::bitset<8>(letter));
return;
}
};
PLUMA_INHERIT_PROVIDER(RNCypher, CryptoBase);
#endif // RNCYPHER_H_INCLUDED
main.cpp (This is part of the plugin)
#include "../Encoder/Pluma/Connector.hpp"
#include "RNCypher.h"
PLUMA_CONNECTOR
bool connect(pluma::Host& host)
{
host.add( new RNCypherProvider() ); //<- Main problem line
return true;
}
Additional Details
I'm compiling on Ubuntu 16.04, using Code::Blocks 16.01.
The second error message seems to not come from Pluma itself, but a file I also had to link, #include <dlfcn.h> (which might be a Linux file?).
I would prefer to use an existing library rather than write my own code as I would like this to be cross-platform. I am, however, open to any suggestions.
Sorry for all of the code, but I believe this is enough to reproduce the error that I am having.
Thank You
Thank you for taking the time to read this, and thank you in advance for your help!
All the best, and happy holidays!
I was not able to reproduce your problem, however looking at
http://pluma-framework.sourceforge.net/documentation/index.htm,
I've noticed that:
in your RNCypher.h file you miss something like
PLUMA_INHERIT_PROVIDER(RNCypher, CryptoBase)
it seems also that there's no file CryptoBase.cpp containing something like
#include "CryptoBase.h"
PLUMA_PROVIDER_SOURCE(CryptoBase, 1, 1);
finally, in CryptoBase.h I would declare a virtual destructor (see Why should I declare a virtual destructor for an abstract class in C++?) and provide a definition to it, while you should not declare a default constructor without providing a definition to it (see for instance Is it correct to use declaration only for empty private constructors in C++?); of course the last consideration is valid unless there's another file in which you have provided such definitions.
I am working on a school project which requires to work with sheepdog. Sheepdog provides a c api which enables you to connect to a sheepdog server.
First i create c source file(test.c) with the following content :
#include "sheepdog/sheepdog.h"
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
then i compile with no error using the following command
gcc -o test test.c -lsheepdog -lpthread
But what i need is to use it with c++ project so i created a cpp file(test.cpp) with the following content :
extern "C"{
#include "sheepdog/sheepdog.h"
}
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
fprintf(stderr, "failed to connect %m\n");
return -1;
}else{
fprintf(stderr, "connected successfully %m\n");
}
return 0;
}
now, when i compiled using the following command :
g++ -o test test.cpp -lsheepdog -lpthread
I got this error :
You can't just wrap extern "C" around a header and expect it to compile in a C++ program. For example, the header sheepdog_proto.h uses an argument named new; that's a keyword in C++, so there's no way that will compile as C++. The library was not designed to be called from C++.
I agree with #PeteBecker. From a quick look around Google, I am not sure there is an easy solution. Sheepdog is using C features and names that don't port well to C++. You might need to hack sheepdog fairly extensively. For example:
move the inline functions out of sheepdog_proto.h into a new C file, leaving prototypes in their place. This should take care of the offsetof errors, e.g., discussed in this answer.
#define new not_a_keyword_new in sheepdog/sheepdog.h
and whatever other specific changes you have to make to get it to compile. More advice from the experts here.
As sheepdog was not designed to be useable from C++ you should build a tiny wrapper in C language to call the functions from sheepdog and only call the wrapper from your c++ code. Some hints to write such a wrapper:
void * is great to pass opaque pointers
extractors can help to access badly named members. If a struct has a member called new (of type T), you could write:
T getNew(void *otherstruct); // declaration in .h
and
T getNew(void *otherstruct) { // implementation in a c file
return ((ActualStruct *) otherstruct)->new;
}
Depending on the complexity of sheepdog (I do not know it) and the part you want to use, it may or not be an acceptable solution. But it is the way I would try facing such a problem.
Anyway, the linker allows mixing modules compiled in C and in C++, either in static linking or dynamic linking.
I’m trying to pass a Structure from a Matlab function in Simulink to an external C++ function using the coder.ceval() and the coder.cstructname(). When I try to run the code on an Arduino Due board using the deploy to hardware tool in Simulink I get the error:
error: invalid use of incomplete type 'struct MyStruct'
error: forward declaration of 'struct MyStruct'
I’m using the example code from mathworks but use a c++ function instead of a c function:
Header use_struct.h:
#include <tmwtypes.h>
typedef struct MyStruct
{
double s1;
double s2;
} MyStruct;
void use_struct(struct MyStruct *my_struct);
C++ function use_struct.cpp:
#include <stdio.h>
#include <stdlib.h>
// #include "use_struct.h" // Doesn’t work when I include it here
extern “C” void use_struct(struct MyStruct *my_struct)
{
double x = my_struct->s1;
double y = my_struct->s2;
}
Matlab function:
structVar.s1 = 1;
structVar.s2 = 2;
if strcmp(coder.target,'rtw'),
coder.cinclude('use_struct.h');
coder.cstructname(structVar, 'MyStruct', 'extern');
coder.ceval('use_struct', coder.ref(structVar));
end
I need it to be a C++ function for the later code. However I also tried it with a c function without the extern “C” but it doesn’t work anyway. Can anyone help me with this problem?
I found the solution. I had to include the c header use_struct.h in the use_struct.cpp also with:
extern "C"
{
#include "use_struct.h"
}
I'm using CUnit for my project unit testing.
I need to test whether I call libc functions with the right parameters & whether I treat their return values the right way.
for example: if I call the bind(...) function - I would like to check which af param I pass & assert if this is the wrong one, and also I would like to emulate it's return value & assert if I check it the right way.
For these purposes I would expect the CUnit environment to have a built-in mechanism to let me call a 'mocked' bind() function while testing and a real bind() function when running the code - but I can't find anything like this.
Can you please tell me if I'm missing something in CUnit, or maybe suggest a way to implement this.
Thanks,
Jo.
Unfortunately, you can't mock functions in C with CUnit.
But you can implement your own mock functions by using and abusing of defines :
Assuming you define UNITTEST when compiling for tests, you can in the tested file (or in a include) define something like this :
#ifdef UNITTEST
#define bind mock_bind
#endif
In a mock_helper.c file that you will compile in test mode :
static int mock_bind_return; // maybe a more complete struct would be usefull here
static int mock_bind_sockfd;
int mock_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
CU_ASSERT_EQUAL(sockfd, mock_bind_sockfd);
return mock_bind_return;
}
Then, in your test file :
extern int mock_bind_return;
extern int mock_bind_sockfd;
void test_function_with_bind(void)
{
mock_bind_return = 0;
mock_bind_sockfd = 5;
function_using_bind(mock_bind_sockfd);
}
glibcmock is a solution of mocking libc function with Google Test. for example:
#include "got_hook.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <sys/socket.h>
#include <mutex>
#include <memory>
struct MockBind {
MOCK_METHOD3(Bind, int(int, const struct sockaddr*, socklen_t));
};
static MockBind *g_mock{nullptr};
static int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
return g_mock->Bind(sockfd, addr, addrlen);
}
static std::mutex g_test_mutex;
TEST(BindTest, MockSample) {
std::lock_guard<std::mutex> lock(g_test_mutex);
std::unique_ptr<MockBind> mock(g_mock = new MockBind());
testing::GotHook got_hook;
ASSERT_NO_FATAL_FAILURE(got_hook.MockFunction("bind", (void*)&Bind));
// ... do your test here, for example:
struct sockaddr* addr = nullptr;
EXPECT_CALL(*g_mock, Bind(1, addr, 20)).WillOnce(testing::Return(0));
EXPECT_EQ(0, bind(1, addr, 20));
}
Following an example at: http://www.learncpp.com/cpp-tutorial/47-structs/ relating to structs, and when I tried to compile this program:
#include <iostream>
void PrintInformation(Employee sEmployee)
{
std::cout<<"ID: "<<sEmployee.nID<<std::endl;
std::cout<<"Age: "<<sEmployee.nAge<<std::endl;
std::cout<<"Wage: "<<sEmployee.fWage<<std::endl;
}
struct Employee {int nID;int nAge;float fWage;};
int main()
{
Employee abc;
abc.nID=123;
abc.nAge=27;
abc.fWage=400;
// print abc's information
PrintInformation(abc);
return 0;
}
I get the following:
Why is that?
Thanks.
You need to declare the struct before the function that attempts to use it.
C (and by extension, C++) were designed for "single-pass" compilation. Therefore, everything must be available to the compiler by the time it's required.