ctypes: accessing members of a structure from its pointer - ctypes

I am trying to access a c++ function from python with following definition:
int PEQueryJob(void *Handle, char *jobId, JobResults **results) {
// Allocate Memory to results structure and fill its members
}
Python code:
class JobProgress(Structure):
_fields_ = [('JobStatus', c_int),
('queueTime', c_uint32),
('analyseTime', c_uint32),
('itemCount', c_uint32),
('completeTime', c_uint32),]
class JobResults(Structure):
_fields_ = [('JobProgress', JobProgress),
('modifiedDataCreated', c_uint32),
('scanResult', c_char_p),
('scanLength', c_uint64),
('metadataLength', c_uint32),
('metadata', MetadataItem),
('modifiedData', c_char_p),
('modifiedDataLength', c_uint64),]
queryjob = lib.PEQueryJob
job_results = POINTER(JobResults)()
queryjob(Handle, submitjob_jobid, byref(job_results))
C definitions:
typedef enum JobStatus {
QUEUED = 0,
IN_PROGRESS,
COMPLETE,
FAILED,
REMOVED
} JobStatus;
typedef struct _MswJobProgress {
JobStatus status;
Uint32 queueTime;
Uint32 analyseTime;
Uint32 itemCount;
Uint32 completeTime;
} Jobprogress;
typedef struct JobResults {
JobProgress progress;
Uint32 modifiedDataCreated;
char * scanResult;
Uint64 scanLength;
Uint32 metadataLength;
Item** metadata;
char * modifiedData;
Uint64 modifiedDataLength;
} JobResults;
Please let me know the correct way of passing the arguments just in case if there is any issue
How do i Access the members of job_results structure which was filled by C++ code??

Related

Trying to initialize an array of stuct inside a struct, but getting storage/memory pointer error

I am trying to create a voting smart contract in solidity.
But I cannot get a hand on how to initialize Vote.differentVotes in side my function createVote() :
my structs
struct Vote_element {
string name;
uint numberOfVotes;
}
struct Vote{
string title;
address creator;
Vote_element[10] differentVotes;
bool done;
}
the function I am having issues with.
function createVote(string memory _title , string[] memory _elements) public {
Vote storage v;
for(uint i = 0; i < _elements.length; i++)
v.differentVotes[i] = Vote_element(_elements[i], 0); // error here
v.title = _title; // error here
v.creator = msg.sender; // error here
v.done = false; // error here
all_votes.push(v); // error here
}
I got the following error everywhere but I do not understand it.
This variable is of storage pointer type and can be accessed without prior assignment,
which would lead to undefined behaviour.
Can someone guide me ?
Try this:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract StudentVotes {
Vote[] all_votes;
struct Vote_element {
string name;
uint numberOfVotes;
}
struct Vote{
string title;
address creator;
Vote_element[10] differentVotes;
bool done;
}
function createVote(string memory _title , string[] memory _elements) public {
// Before initializing the variable into a struct, you must push the struct into
// Votes' array.
Vote storage v = all_votes.push();
// Then you can initialize the each variable into a struct
v.title = _title;
v.creator = msg.sender;
for(uint i = 0; i < _elements.length; i++)
v.differentVotes[i] = Vote_element(_elements[i], 0);
v.done = false;
}
}

MySqlX (C connector) with Dart's ffi brings error "NoSuchMethodError: The method 'FfiTrampoline' was called on null."

I am trying to directly connect to MYSQL with Dart using Dart's ffi package and the native C-Connector of MYSQL.
My Dart code is:
import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef CFun = Pointer Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer>?);
typedef DartFun = Pointer Function(Pointer<Utf8>, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer>?);
void main() {
final lib = DynamicLibrary.open('/usr/lib64/libmysqlcppconn8.so.2');
final fc = lib.lookup<NativeFunction<CFun>>('mysqlx_get_session');
print('We have C: $fc');
final DartFun fd = fc.asFunction();
print('We have Dart: $fd');
Pointer<Pointer>? error;
Pointer? session;
session = fd('localhost'.toNativeUtf8(), 33060, '*user*'.toNativeUtf8(), '*password*'.toNativeUtf8(), ''.toNativeUtf8(), error);
}
When running this I get this output:
We have Pointer<NativeFunction<(Pointer<Utf8>, Int32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer<NativeType>>?) => Pointer<NativeType>>>: address=0x7f5b9c78f770
We have Closure: (Pointer<Utf8>, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer<NativeType>>?) => Pointer<NativeType>
Unhandled exception:
NoSuchMethodError: The method 'FfiTrampoline' was called on null.
Receiver: null
Tried calling: FfiTrampoline()
#0 FfiTrampoline (dart:ffi)
#1 main (package:greudb/src/connection.dart:37:14)
#2 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
Trying the same in C it works perfectly:
#include <mysql-cppconn/mysqlx/xapi.h>
#include <stdio.h>
int main()
{
mysqlx_session_t *session = 0;
mysqlx_error_t *error = 0;
session = mysqlx_get_session("localhost", 33060, "*user*", "*password*", "", &error);
if(error != 0) {
printf("%s/n", mysqlx_error_message(error));
}
return 0;
}
I guess my Dart Function signatures are not correct, but no matter what I try it does not help.
MySQL's C documentation is here: https://dev.mysql.com/doc/dev/connector-cpp/8.0/group__xapi__sess.html
I am using Linux Fedora 33, MySQL community server 8, MySQL Connector C/C++ 8, Dart 202.8488.
After a bit of looking around, it appears you can create the appropriate type for error using:
final error = calloc<Pointer>();
which under the hood calls calloc.allocate<Pointer>(...) with the appropriate byteCount. As this is unmanaged memory, you'll need to remember to release it by calling:
calloc.free(error);
once you're done with it.
Thankfully, the mysqlx API seems to treat all the structs as opaque, so you can determine what the actual error was by doing something like the following:
final message = errorMessage(error.value);
print(message.toDartString());
On the topic of releasing memory, the Pointer<Utf8> values created by calling toNativeUtf8() also need to be freed.
Putting all that together:
import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef _GetSession = Pointer Function(Pointer<Utf8>, Int32, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer>);
typedef GetSession = Pointer Function(Pointer<Utf8>, int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Pointer>);
typedef _CloseSession = Void Function(Pointer);
typedef CloseSession = void Function(Pointer);
typedef _ErrorMessage = Pointer<Utf8> Function(Pointer);
typedef ErrorMessage = Pointer<Utf8> Function(Pointer);
void main() {
final lib = DynamicLibrary.open('/usr/lib64/libmysqlcppconn8.so.2');
final GetSession getSession = lib.lookup<NativeFunction<_GetSession>>('mysqlx_get_session').asFunction();
final CloseSession closeSession = lib.lookup<NativeFunction<_CloseSession>>('mysqlx_session_close').asFunction();
final ErrorMessage errorMessage = lib.lookup<NativeFunction<_ErrorMessage>>('mysqlx_error_message').asFunction();
final host = 'localhost'.toNativeUtf8();
final user = 'user'.toNativeUtf8();
final password = 'password'.toNativeUtf8();
final database = ''.toNativeUtf8();
final error = calloc<Pointer>();
final session = getSession(host, 33060, user, password, database, error);
calloc.free(host);
calloc.free(user);
calloc.free(password);
calloc.free(database);
if (error.value != nullptr) {
final message = errorMessage(error.value);
print(message.toDartString());
calloc.free(error);
return;
}
// Do something with session
closeSession(session);
}

error: invalid new-expression of abstract class type ‘gr::zeromq::base_sink_impl’

namespace gr {
namespace zeromq {
class base_impl : public virtual gr::sync_block
{
public:
base_impl(int type, size_t itemsize, size_t vlen, int timeout, bool pass_tags);
virtual ~base_impl();
protected:
zmq::context_t *d_context;
zmq::socket_t *d_socket;
size_t d_vsize;
int d_timeout ;
bool d_pass_tags ;
};
class base_sink_impl : public base_impl
{
public:
base_sink_impl(int type, size_t itemsize, size_t vlen, char *address, int timeout, bool pass_tags, int hwm);
protected:
int send_message(const void *in_buf, const int in_nitems, const uint64_t in_offset);
};
} // namespace zeromq
}
`main(){
gr::zeromq::base_sink_impl *d_zeromq;
d_zeromq = new gr::zeromq::base_sink_impl(ZMQ_PUSH, sizeof(float), 1, "tcp://127.0.0.1:9098", 100, false, -1);
return 0;
}`
Hello!
After run this code, I have this error:
error: invalid new-expression of abstract class type ‘gr::zeromq::base_sink_impl’
_sink_impl(ZMQ_PUSH, sizeof(float), 1, "tcp://127.0.0.1:9098", 100, false, -1);
^
I'm not sure how to solve this error. I think I'm making wrong the constructor....
Please, any help will really appreciate it. Thanks
I find the error: the super class gr::sync_block has a virtual method called work.
I declared int work(int, gr_vector_const_void_star&, gr_vector_void_star&); inside the class base_impl and compiled.
Unfortunately, I can't run the project as It seems I have to configurate one of the CMakeList.txt to recognize zmq.hpp. It also seems I have to configurate the CMakeList.txt in my swig directory as I'm trying to do a GNURadio OOT Block using ZeroMQ.
Any help with it , I really Appreciate it.
Pd: If I resolve it, I 'll post it here:
GNU Radio OOT block : AttributeError: 'module' object has no attribute 'pthread' (using ZeroMQ sockets)

Custom SWIG Wrapping to Handle Nested C Structures

I have the below C struct that has a couple nested structures that have proven to be difficult to deal with using my knowledge of SWIG. Everything below is easily wrapped by SWIG execept for saddr (C socket address) and mac[6] (C array representing a MAC address). Since SWIG gives me the pointer value (SWIGTYPE_p_unsigned_char and SWIGTYPE_p_sockaddr), I would like to somehow call a helper C function to convert the pointer to a char*. I have the helper function, but I don't know the best way to plug this into SWIG. Is there any way to configure the getMac() and getSaddr() to call the helper function?
C Structure Trying To Wrap:
%rename (Details) details_t_;
typedef struct details_t_ {
uint16_t code;
char *name;
**sockaddr *saddr;**
uint32_t saddr_len;
uint8_t flag;
ios_boolean is_child;
**unsigned char mac[6];**
} details_t;
Generated Java Code:
public void setMac(SWIGTYPE_p_unsigned_char value) {
TestJNI.Details_mac_set(swigCPtr, this, SWIGTYPE_p_unsigned_char.getCPtr(value));
}
public SWIGTYPE_p_unsigned_char getMac() {
long cPtr = TestJNI.Details_mac_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_unsigned_char(cPtr, false);
}
public void setSaddr(SWIGTYPE_p_sockaddr value) {
TestJNI.Details_saddr_set(swigCPtr, this, SWIGTYPE_p_sockaddr.getCPtr(value));
}
public SWIGTYPE_p_sockaddr getSaddr() {
long cPtr = TestJNI.Details_saddr_get(swigCPtr, this);
return (cPtr == 0) ? null : new SWIGTYPE_p_sockaddr(cPtr, false);
}
Proposed SWIG.i Changes:
%module Test
%rename (realId) details_t_::mac;
%typemap(javacode) struct details_t_ %{
public String getMac() {
return Test.getMacAddressAsString(this);
//this is a pointer to details_t_ struct
}
%};
%rename (Details) details_t_;
typedef struct details_t_ {
uint16_t code;
char *name;
**sockaddr *saddr;**
uint32_t saddr_len;
uint8_t flag;
ios_boolean is_child;
**unsigned char mac[6];**
} details_t;
You can do this with a javacode typemap, e.g.:
%module test
%rename (realId) Sample::id;
%typemap(javacode) struct Sample %{
public byte getId() {
return 100-getRealId(); // Transform the real call
}
public void setId(byte value) {
setRealId(value+100);
}
%};
struct Sample {
char id;
};
Renames the generated getId() and setId(), but provides a Java get/set which can be written in terms of the SWIG generated (but renamed) one. You might want to make the SWIG generated ones private though.

In C++, how to use find_if on a map with a functor when keys are struct with strings?

I have a stl::map which key type is a custom struct. I want to know if this map already has a key with a specific string as component (noted as "id" below), whatever the value of its other components. Inspired by this answer and this one also, I try to use stl::find_if with a custom functor:
map<myStruct, vector<size_t> > myMap;
struct myStruct
{
string a, b, c, id;
};
struct checkId : unary_function<pair<myStruct, vector<size_t> >, bool>
{
private:
string _exp;
public:
checkId (myStruct x) : _exp(x.id) {}
bool operator() (const pair<myStruct, vector<size_t> > & p) const
{
return p.first.id.compare(_exp) == 0;
}
};
map<myStruct, vector<size_t> >::iterator it;
myStruct newS; // to be initialized, but not shown here
it_mP2P = find_if(myMap.begin(), myMap.end(), checkId(newS));
When I compile this, gcc returns me:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = myStruct]’:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:347: instantiated from ‘_Tp& std::map<_Key,_Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = myStruct, _Tp = std::vector<long unsigned int, std::allocator<long unsigned int> >, _Compare = std::less<myStruct>, _Alloc = std::allocator<std::pair<const myStruct, std::vector<long unsigned int, std::allocator<long unsigned int> > > >]’
myprogram.cpp:386: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’
Does this mean that I have to overload the operator "<" to work with my custom struct if I want to use my functor "checkId"? How can I do this? I am not a C++ expert,so thanks in advance for any piece of code.
http://codepad.org/VYNqdZeF
struct myStruct
{
std::string a, b, c, id;
bool operator<(const myStruct& rhs) const //HERES THE MAGIC
{return id < rhs.id;} //WHEEEEEEEEEEEE!
};
This is required to make std::map<myStruct, stuff> work, without passing a custom comparison functor.
It's got nothing to do with checkId. The following demonstrates the same problem:
map<myStruct, vector<size_t> > myMap;
struct myStruct
{
string a, b, c, id;
};
std::map is a sorted map (it's usually implemented as a binary search tree)... the key type (myStruct in this case) must have operator< implemented simply to construct the map.
If you don't need fast lookups, you can just use a vector< pair< myStruct, vector<size_t> > >; if you need fast lookups, you have to add some kind of structure to myStruct. For a std::map this must be a comparison operator; alternatively you can use a std::unordered_map (in C++11; this is usually implemented as a hash table) -- in this case you will need to implement a hash function.
See the documentation of std::map and std::unordered_map for more details.
This has nothing to do with your use of find_if.
For a type to be a key of a map, it needs to be comparable, either by implementing operator< or by providing a comparator as a template parameter of the map.
Mooing Duck's answer is the easiest to do, but not the most flexible
if you go and write
struct myStruct
{
std::string a, b, c, id;
bool operator<(const myStruct& rhs) const
{return id < rhs.id;}
};
then all your maps that have myStruct as a key, will have to be sorted
by id.
Suppose you have one map that needs to be compared by a, and another one by b. If you put operator<() inside your myStruct, then you will have coupled the struct with its users, tightly, which is not good programming practice.
Instead, you could set a compare function to each map:
struct myStruct
{
std::string a, b, c, id; // keep your struct unchanged, and independent of clients
};
bool Compare_by_a(const myStruct &s1, const myStruct& s2) {
return s1.a < s2.a;
}
bool Compare_by_b(const myStruct &s1, const myStruct& s2) {
return s1.b < s2.b;
}
bool Compare_by_id(const myStruct &s1, const myStruct& s2) {
return s1.id < s2.id;
}
map<myStruct, vector<size_t>, Compare_by_a > map1;
map<myStruct, vector<size_t>, Compare_by_b > map2;
map<myStruct, vector<size_t>, Compare_by_id > map3;