I have defined the following structure:
struct com_NetworkStruct
{
enum com_NetworkStatus status;
char IPV4_Addr[COM_IPV4_ADDR_LENGTH];
char IPV4_Netmask[COM_IPV4_ADDR_LENGTH];
char IPV4_DNS1[COM_IPV4_ADDR_LENGTH];
char IPV4_DNS2[COM_IPV4_ADDR_LENGTH];
int IPV4_DHCP_Enabled;
int IPV6_Supported;
int IPV6_Enabled;
struct com_IPv6_Data *IPV6_Address_List;
char HW_Addr[COM_ETH_MAC_ADDR_LENGTH];
int MTU_Size;
int Link_Speed;
enum com_LinkType Link_Type;
};
And the following method definition:
int foo(struct com_NetworkStruct **netinfo);
This is the main function and how i call the function:
int main(int argc, char const *argv[])
{
int ret;
char data_aux[200];
struct com_NetworkStruct *netinfo = NULL;
ret = foo(&netinfo);
memset(data_aux, 0, sizeof(data_aux));
sprintf(data_aux, "%s", netinfo->IPV4_Addr);
cout<<string(data_aux)<<endl;
return 0;
}
The problem is when I try to read the data of the IPV4_Addr value since it sends me the following error:
Error: #289: no instance of constructor "std::basic_string<_CharT, Traits, Alloc>::basic_string [with CharT=char, Traits=std::char_traits<char>, _Alloc=std::allocator<char>]" matches the argument list
argument types are: (const char [20], char [16])
I already tried this, but nothing works:
&netinfo->IPV4_Addr
netinfo.IPV4_Addr
string(netinfo->IPV4_Addr)
Related
On Debian I try to mock system function bind to bind an interface address to a socket. To set an ip address I think I have to use side effects on a parameter of bind. I use this code:
extern "C" {
int mysocket();
}
// --- mock bind -------------------------------------------
class BindInterface {
public:
virtual ~BindInterface() {}
virtual int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen) = 0;
};
class BindMock : public BindInterface {
public:
virtual ~BindMock() {}
MOCK_METHOD(int, bind, (int, const struct sockaddr*, socklen_t), (override));
};
BindInterface* ptrBindMockObj = nullptr;
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen) {
return ptrBindMockObj->bind(sockfd, addr, addrlen);
}
TEST(MockTestSuite, bind_address_to_a_socket)
{
using ::testing::_;
using ::testing::Return;
using ::testing::DoAll;
using ::testing::SetArgPointee;
using ::testing::SetArgReferee;
struct sockaddr_in my_addr = {0};
BindMock bindMockObj;
ptrBindMockObj = &bindMockObj;
my_addr.sin_family = AF_INET;
EXPECT_EQ(inet_pton(AF_INET, "192.168.55.66", &my_addr.sin_addr.s_addr), 1);
EXPECT_CALL(bindMockObj, bind(_, _, _))
.WillOnce(DoAll(SetArgPointee<1>((struct sockaddr*)my_addr),
SetArgReferee<2>(sizeof(my_addr)),
Return(0)));
EXPECT_EQ(mysocket(), EXIT_SUCCESS);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
It doesn't work because the compiler complains invalid cast as follows:
test_mylib.cpp: In member function ‘virtual void MockTestSuite_bind_address_to_a_socket_Test::TestBody()’:
test_mylib.cpp:52:42: error: invalid cast from type ‘sockaddr_in’ to type ‘sockaddr*’
52 | .WillOnce(DoAll(SetArgPointee<1>((struct sockaddr*)my_addr),
| ^~~~~~~~~~~~~~~~~~~~~~~~~
Seems I do not really understand what SaveArgPointee<N>(pointer) is doing. What I'm doing wrong with types and cast?
UPDATE:
With the suggestion from the answer of #Quarra to define the ACTION_P outside the TEST body I get two error messages within a bunch of stacked calls:
googlemock/include/gmock/gmock-actions.h:1116:56: error: static assertion failed: Argument must be a reference type.
1116 | static_assert(std::is_lvalue_reference<argk_type>::value,
| ^~~~~^
--- snip ---
test_mylib.cpp:33:54: error: no match for ‘operator=’ (operand types are ‘sockaddr’ and ‘const sockaddr_in’)
33 | ACTION_P(AssignSockAddr, param) { *(sockaddr*)(arg0) = param; }
| ~~~~~~~~~~~~~~~~~~~^~~~~~~
In file included from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
from /usr/include/netinet/in.h:23,
from test_mylib.cpp:7:
I agree that it's strange that your example doesn't compile: it's trying to change the pointer to const socaddr, not const pointer...
You can define your own action and use it like that:
ACTION_P(AssignSockAddr, param) { *(sockaddr*)(arg0) = param; }
TEST(MockTestSuite, bind_address_to_a_socket) {
// [ rest of the test code here ]
EXPECT_CALL(bindMockObj, bind(_, _, _)).WillOnce(
DoAll(WithArg<1>(AssignSockAddr(my_addr)),
SetArgReferee<2>(sizeof(my_addr)),
Return(0)));
EXPECT_EQ(mysocket(), EXIT_SUCCESS);
}
Description:
Declaration of strstr:
char *strstr(const char *haystack, const char *needle);
Definition of my function:
hostinfo_t *extract_host_from_url(const char *url) {
/* ... */
char *scheme_pos = strstr(url, "://");
/* ... */
}
How I use it:
void rewrite_url(string &url) {
/* ... */
hostinfo_t * hostinfo = extract_host_from_url(url.c_str());
/* ... */
}
Error info:
error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
char *scheme_pos = strstr(url, "://");
Question:
Where do things go wrong?
C++ declaration of strstr, as given in <cstring> is overloaded
const char* strstr( const char* str, const char* target );
char* strstr( char* str, const char* target );
With your set of arguments, you are calling the first function, which is why the return type is const char*.
I have a class which takes the main command line arguments (eg, -B, -a, etc) and does something with them, but also i would like to be able to instantiate that function without passing the command line arguments, so for example:
constructor:
myClass(int argc, const char **argv){
<initialise class with flags from argv>
}
myClass() : myClass(2, "-B") {}
}
Here i am trying to instantiate myClass with the flag "-B", but it keeps giving me the error:
no known conversion for argument 3 from ‘const char [3]’ to ‘const char**’
so i was wondering what i need to do to pass a value in as const char**?
First level is pointer to first pointer to char *. Second level is pointer to the first const char of c-string.
> cdecl explain "const char ** args"
declare args as pointer to pointer to const char
If you have -std=c++11 available, you can use this example (but it can be rewritten to use old standard):
#include <iostream>
#include <vector>
#include <string>
class test {
public:
test(const std::vector<std::string> & args) {
for (auto & arg : args) {
std::cout << arg << "\n";
}
}
test() : test{{"-B"}} {}
};
int main(int argc, const char ** argv) {
test sth{{argv+1, argc+argv}}; // skip program name here
test sth_else;
}
const char** is pointer to const char*. In your case, you intend to pass multiple arguments as part of argv, so you can pass something like below:
const char* argv[] = {"<program name>", "B"};
myClass m(2, argv);
Note: const char** x & const char* x[] are same. The 2nd syntax is helpful when one wants to "represent" an array.
Here I am giving a way to mimic the main(int, char**) function argument for your internal test. If you want to pass from default constructor to argument constructor then all the above stuff will have to go global.
I can't understand why this code prints 1 in C, but other digit in C++?
#include <stdio.h>
static char T = 'a';
int main(int argc, char** argv) {
struct T { char X[2]; };
printf("size of T is %zu\n", sizeof(T));
}
And why this code prints 1 in both C and C++?
#include <stdio.h>
int main(int argc, char** argv) {
static char T = 'a';
struct T { char X[2]; };
printf("size of T is %zu\n", sizeof(T));
}
Can somebody explain me this a little bit, please?
Because in C the struct is called struct T and not only T. In C++ the local definition of struct T will hide the global variable T:
#include <stdio.h>
static char T = 'a'; // (1)
int main(int argc, char** argv) {
// `struct T` shadows outer `T` in C++
struct T { char X[2]; }; // (2)
// C: sizeof char (1); C++: sizeof struct T (2)
printf("size of T is %u\n", sizeof(T));
// C/C++: sizeof struct T (2)
printf("size of struct T is %u\n", sizeof(struct T));
}
On the other hand, when both declarations are in the same naming context, the ambiguity of the identifier T will result in the same results, since C++ expects you to specify that you really want to use the struct and not the char T:
#include <stdio.h>
int main(int argc, char** argv) {
static char T = 'a';
struct T { char X[2]; };
printf("size of T is %u\n", sizeof(T)); // sizeof (char)
printf("size of struct T is %u\n", sizeof(struct T));// sizeof struct T
}
Which results in the same size for both C and C++.
How to avoid this mistakes
Usually compilers do know that the identifier is ambiguous, but the warning is often hidden. Use compiler flags to show warnings, in GCC -Wall -Wextra are the most useful for usual programming:
test.cc: In function »int main(int, char**)«:
test.cc:5:43: Warning: unknown converting symbol »z« in format [-Wformat]
test.cc:5:43: Warning: to many arguments for format [-Wformat-extra-args]
test.cc: global:
test.cc:3:5: Warning: unused parameter »argc« [-Wunused-parameter]
test.cc:3:5: Warning: unused parameter »argv« [-Wunused-parameter]
test.cc:2:13: Warning: »T« defined, but not used [-Wunused-variable]
In this case one will see that the global static char T has been defined, but never used.
In C, when a structure is declared, it is of type struct <name of struct> and not just the name of the struct. That is the reason. To avoid confusion, people use typedef to simplify the declarations in C
As mentioned by others, in the first snippet the local struct T will hide the static var in C++. However, to fully understand what's going on, you also have to talk about name disambiguation. In the second code snippet, struct T isn't hiding T - they're in the same scope.
I'm having serious trouble figuring out what is making certain function calls ambiguous and others are fine. I have the following overloaded function calls within my BitPacker object:
static __declspec(dllexport) void PackBits(void *dstBuffer, unsigned long long data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, bool data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, float data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, double data, unsigned int &offsetBits, const unsigned int numBits);
I am trying to make the following call from within another object that is including "BitPacker.h":
void Date::ReflectToBitBuffer(void)
{
unsigned int offsetBits = 0;
BitPacker::PackBits(m_packedBuffer, m_year, offsetBits, YR_BITS);
BitPacker::PackBits(m_packedBuffer, m_month, offsetBits, MO_BITS);
BitPacker::PackBits(m_packedBuffer, m_day, offsetBits, DY_BITS);
}
"m_year", m_month", and "m_day" are int member variables. However I am getting the following errors when attempting to compile:
error C2668: 'BitPacker::PackBits' : ambiguous call to overloaded function
could be 'void BitPacker::PackBits(void *,double,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,float,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,bool,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,unsigned __int64,unsigned int &,const unsigned int)'
while trying to match the argument list '(char *, int, unsigned int, )'
So I wrote a test solution with the following main.cpp to test out overloads and what I have below compiles fine:
void OverloadTest(float f);
void OverloadTest(int n, int &numbits);
void OverloadTest(double d);
void OverloadTest(char c, int &numbits);
void OverloadTest(long long l, int &numbits);
void OverloadTest(long long *l);
void OverloadTest(bool b);
int main(int argc, int *argv)
{
int myInt = 77;
bool myBool = true;
float myFloat = 3.14159f;
double myDouble = 1.57;
long long myLongLong = 12345;
long long *ptrLongLong = NULL;
char myChar = 'q';
int myNumBits = 10;
OverloadTest(myInt, myNumBits);
OverloadTest(myFloat);
OverloadTest(myDouble);
OverloadTest(myLongLong, myNumBits);
OverloadTest(ptrLongLong);
OverloadTest(myChar, myNumBits);
OverloadTest(myBool);
return 0;
}
void OverloadTest(float _f) { int x = 0; }
void OverloadTest(int _n, int &_numbits) { int x = 0; }
void OverloadTest(double _d) { int x = 0; }
void OverloadTest(char _c, int &_numbits) { int x = 0; }
void OverloadTest(long long _l, int &_numbits) { int x = 0; }
void OverloadTest(long long *_l) { int x = 0; }
void OverloadTest(bool b) { int x = 0; }
I even tried to simplify:
void Date::ReflectToBitBuffer(void)
{
unsigned int offsetBits = 0;
unsigned int testVar2 = 12;
unsigned int testVar1 = 1977;
BitPacker::PackBits(m_packedBuffer, testVar1, offsetBits, testVar2);
}
And I still get the ambiguity. If I use a float however I don't. At the moment I am utterly confused why my test scenario does not produce this error. Would anyone be able to shed some light on what the problem is because the function prototype signatures in the first code example look to me to be different enough to allow it to compile.
It looks like that "int" can be casted into all 4 types of your overloaded function and none of them exactly matches your call. Maybe that's the problem.
Try making your call exactly match the function definiton or making an int version for your call?