I'm writing in c++ a graphic user interfaced program and I need to create a threads in the program.
so I'm using System::Threading namespace to get my goal.
The function that I want to use as thread is a class member function, so here is what I've done:
Server::Server() // constructor
{
System::Threading::Thread^ T = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this, this->RunServer)); // Server::RunServer
T->Start();
}
since it gave me those errors:
Error 2 error C3350: 'System::Threading::ThreadStart' : a delegate
constructor expects 2 argument(s)
Error 1 error C3867: 'Server::RunServer': function call missing
argument list; use '&Server::RunServer' to create a pointer to
member
I tried this call:
Server::Server() // constructor
{
System::Threading::Thread^ T = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(&Server::RunServer));
T->Start();
}
and received this errors:
Error 1 error C3364: 'System::Threading::ThreadStart' : invalid
argument for delegate constructor; delegate target needs to be a
pointer to a member
function
2 IntelliSense: invalid delegate initializer -- function is not a
member of a managed
class
as far as I know the second try did not succeed because Server::RunServer doesn't have address, so it's like to do &1.
by the way I tried to use the ThreadStart to create thread of none class memeber function and it worked fine.
I'm using win7 - visual studio 2012. How to make it work?
EDIT:
Server declaration:
class Server
{
public:
/* Fields */
std::string Port;
std::string Host;
WSADATA wsaData;
int ListenResult;
SOCKET ListenSocket;
SOCKET* ClientSocket;
SOCKADDR_IN* ADDR;
int ADDRSize;
struct addrinfo *result;
struct addrinfo hints;
std::vector<Client> Clients;
/* Methods */
Server();
std::wstring StringW(char* String);
void Print(std::wstring String);
std::wstring CurrentTime();
void ParseServerIni();
void RunServer();
void PartToString(Part* _Part);
void InsertListItem(std::string String);
void ClientHandler(SOCKET* _Sock, SOCKADDR_IN* _ADDR);
int ParsePacket(Packet &_Packet, int _Bytes, Byte** _PacketBlock);
};
You almost got the syntax right.
Assuming the declaration is:
public ref class Server
{
void RunServer();
};
Then you should combine your two approaches, by specifying both the object to invoke the method on, and the address of the method, with the name of the declaring class.
gcnew System::Threading::ThreadStart(this, &Server::RunServer)
Related
I'm attempting to run a function concurrently using QtConcurrent but I'm running into issues with one of the arguments.
As a precursor, lets say I have the following classes and "interfaces":
class DataMessage : public QObject {
Q_OBJECT
// ... fields and methods
};
class ITimeStampInfo {
public:
virtual QDateTime timestamp() const = 0;
};
Q_DECLARE_INTERFACE(ITimeStampInfo, "My.TimeStampInfo/1.0")
class IDataLengthInfo {
public:
virtual int dataLength() const = 0;
};
Q_DECLARE_INTERFACE(IDataLengthInfo, "My.IDataLengthInfo/1.0")
class DataMessage1 : public DataMessage, public ITimeStampInfo {
Q_OBJECT
Q_INTERFACES(ITimeStampInfo)
// other fields, etc
QDateTime timestamp() const;
};
class DataMessage2 : public DataMessage, public IDataLengthInfo {
Q_OBJECT
Q_INTERFACES(IDataLengthInfo)
// other fields
int dataLength() const;
};
And a class function called processDataMessages:
void MyClass::processDataMessages(DataMessage *msg) {
// Previous to this function being called, concrete `DataMessage`
// instances are created and passed by pointer into this function
// Determine the data in the message
IDataLengthInfo *dl = qobject_cast<IDataLengthInfo*>(msg);
if (dl) {
qDebug() << "Got a message with IDataLengthInfo";
}
ITimeStampInfo *ts = qobject_cast<ITimeStampInfo*>(msg);
if (ts) {
qDebug() << "Got a message with ITimeStampInfo";
}
// etc
}
This processDataMessages is called in a slot. During normal operation, this function works perfectly and the qDebug() statements execute as expected as the pointer is correct - for example, inspecting the pointer type in the debugger results in a DataMessage1 type, for instance
I now want to run this function asynchronously as potentially, there may be a bit of work to do. If I try to execute this function using QtConcurrent::run from within the slot as follows:
void MyClass::dataReceived(DataMessage *msg) {
// this->processDataMessages(msg);
QtConcurrent::run(this, &MyClass::processDataMessages, msg);
}
Now when I break on the first qobject_cast line in the processDataMessages function, I can see that the msg pointer is of type DataMessage and not any of the DataMessage1 or DataMessage2 types.
Something is being lost during the operation of QtConcurrent::run and its probably something dumb I've missed.
Ok, so as it turns out, the following code works:
QFuture<void> f = QtConcurrent::run(this, &MyClass::processDataMessages, msg);
// Wait for the function to finish
f.waitForFinished();
Doesn't really seem any different to the original but something in the return value may be maintaining state??
In the following C++ code (from a Microsoft COM header file), what is the part that starts with template<class Q>...?
I am thoroughly confused for other reasons as well, as although a struct is in use, it has class-like elements; for example, the public keyword.
extern "C++" {
struct IUnknown {
public:
virtual HRESULT WINAPI QueryInterface(REFIID riid,void **ppvObject) = 0;
virtual ULONG WINAPI AddRef(void) = 0;
virtual ULONG WINAPI Release(void) = 0;
template<class Q> HRESULT WINAPI QueryInterface(Q **pp) { return QueryInterface(__uuidof(*pp),(void **)pp); }
};
}
The part that starts with template<class Q> HRESULT WINAPI QueryInterface is a template member function. In other words, it's a function template that's a member of a class (or struct, in this case).
Being a template means you can pass any interface type as its parameter, and the compiler will generate a function to query an object for an interface of that type:
IFoo *x;
IBar *y;
if (foo.QueryInterface(&x) != S_OK) {
// use x->whatever to invoke members of IFoo
}
if (foo.QueryInterface(&y) != S_OK) {
// use y->whatever to invoke members of IBar
}
Since it's a function template, the compiler deduces the type for Q from the type of the parameter you pass so when you pass an IFoo **, Q has the type IFoo, and when you pass an IBar **, Q has the type IBar.
In C++, the only difference between a class and struct is that member visibility in a class defaults to private, but in a struct defaults to public (so the public: tag isn't accomplishing anything in this case).
I have written a header file with one basic data structure.
ProdList.h
#ifndef LISTOFITEMS_H
#define LISTOFITEMS_H
struct ListOfItems
{
public:
std::string fdcustid;
std::string fdstkid;
std::string fdordisquantity;
std::string fdordsstatus; // <> 'H'
std::string fdordhtype; // <> 'A'
};
#endif /* GRANDFATHER_H */
now that I have a data structure I include it in the class definition and use the data structure "ListOfItems" in the class "ProdContainer".
ProdContainer.h
#include "ProdList.h"
class ProdContainer
{
public:
ProdContainer(void);
~ProdContainer(void);
static void SetNumberOfElements(int Elements);
std::vector<ListOfItems> Items;
}
now when i write the following in Main.
int _tmain(int argc, _TCHAR* argv[])
{
ProdContainer myobject;
myobject.Items.resize(12);
printf("The size of Items is %i \n", myobject.Items.size());
return 0;
}
All goes as expected and I get the following output.
The size of Items is 12
Which is all fine and good. However, I want to encapsulate the data within the class and only allow access through class functions.
The problem arises when I add the following code to "SetNumberOfElements" implementation.
void ProdContainer::SetNumberOfElements(int Elements)
{
Items.resize(Elements);
}
When I try to compile this "error C2228 left of '.resize' must have class/struct/union" appears and I am at a loss at what to do next.
I have searched high and low and cant seem to find any posts matching this particular problem, it's probably a schoolboy error. I've checked the MSDN site on error C2228 and as far as I can see Items is a substantiated variable of struct type ListOfItems, so I can't see why this error is appearing.
Is there a method for accessing a vector of a struct or some other aspect that I just can't see.
Please help, I am just about ready to explode.
You can only access static data from static functions. So change this
static void SetNumberOfElements(int Elements);
To this
void SetNumberOfElements(int Elements);
You cannot access non-static class members from the static function.
What you can do is to "switch" from static to non-static.
static void SetNumberOfElements( void * lParam, int Elements)
{
((ProdContainer*)lParam)->Items.resize( Elements );
}
Use it like this inside your class:
SetNumberOfELements( this, 10 );
Here is my header file in Visual C++ Express 2010 (note the last line):
/* custom class header to communicate with LynxMotion robot arm */
using namespace System;
using namespace System::IO::Ports;
public ref class LynxRobotArm
{
public:
LynxRobotArm();
~LynxRobotArm();
void connectToSerialPort(String^ portName, int baudRate);
void disconnectFromSerialPort();
void setCurrentPosition(int channel, int position);
int getCurrentPosition(int channel);
void moveToPosition(int channel, int position);
private:
void initConnection();
SerialPort^ serialPort;
array<String^> ^serialPortNames;
String^ portName;
int baudRate;
std::vector<int> *currentPosition;
};
I try to assign a value to the vector by using this function;
void LynxRobotArm::setCurrentPosition(int channel, int position)
{
currentPosition[channel] = position;
}
The compiler gives me an error C2679:
binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
I looked up at MSDN and they say:
To use the operator, you must overload it for the specified type or define a conversion to a type for which the operator is defined.
I tried using currentPosition.at(channel) = position but it did not make a difference.
I am stuck... quite new to pointers, noted that using std::vector<int> currentPosition; instead of std::vector<int> *currentPosition; does not compile.
How should my set-function work? (will try getter afterwards..)
I've been trying to figure this out for a few hours now.
In order to start up the audio, I need to create an SDL.AudioSpec object and pass it to SDL.Audio.Open. The problem is, AudioSpec is a class with a private constructor, so when I try to create one I get:
sdl.vala:18.25-18.43: error: `SDL.AudioSpec' does not have a default constructor
AudioSpec audiospec = new SDL.AudioSpec();
^^^^^^^^^^^^^^^^^^^
And if I try to just assign values to it's member vars like a struct (it's a struct in normal sdl) I get:
sdl.vala:20.3-20.25: error: use of possibly unassigned local variable `audiospec'
audiospec.freq = 22050;
^^^^^^^^^^^^^^^^^^^^^^^
I found the valac doc here: http://valadoc.org/sdl/SDL.AudioSpec.html
But it isn't much help at all.
The offending code block looks like this:
// setup the audio configuration
AudioSpec audiospec;
AudioSpec specback;
audiospec.freq = 22050;
audiospec.format = SDL.AudioFormat.S16LSB;
audiospec.channels = 2;
audiospec.samples = 512;
// try to initialize sound with these values
if (SDL.Audio.open(audiospec, specback) < 0)
{
stdout.printf("ERROR! Check audio settings!\n");
return 1;
}
Any help would be greatly appreciated!
Another update, as I'm still having some trouble. I've changed the vapi file, and this is what I have now:
public delegate void AudioCallback (out void* userdata, out uchar stream, int len);
[CCode (cname="SDL_AudioSpec")]
[Compact]
public struct AudioSpec {
public int freq;
public AudioFormat format;
public uchar channels;
public uchar silence;
public uint16 samples;
public uint16 padding;
public uint32 size;
public AudioCallback callback;
public void* userdata;
}// AudioSpec
I have a method that (tries?) to meet this function signature:
public void callback(out void* userdata, out uchar stream, int len)
{
stream = 0;
userdata = null;
}
And assigning it as:
audiospec.callback = gen.callback;
Needless to say, this still isn't working, get lots of errors:
/home/gukid/vala/soundgen.vala.c: In function ‘sound_gen_main’:
/home/gukid/vala/soundgen.vala.c:766:12: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:766:72: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:766:114: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:768:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:769:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
/home/gukid/vala/soundgen.vala.c:770:21: warning: assignment from incompatible pointer type [enabled by default]
/home/gukid/vala/soundgen.vala.c:771:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target’
/home/gukid/vala/soundgen.vala.c:772:11: error: ‘SDL_AudioSpec’ has no member named ‘callback_target_destroy_notify’
error: cc exited with status 256
So I'm at a bit of another sticky point.
3rd post: EUREKA! I have a solution! (debatable :P)
First off, the sdl.vapi looks like:
[CCode (cheader_filename = "SDL.h")]
public delegate void AudioCallback (void* userdata, uchar* stream, int len);
[CCode (cname="SDL_AudioSpec", has_type_id=false)]
public struct AudioSpec {
public int freq;
public AudioFormat format;
public uchar channels;
public uchar silence;
public uint16 samples;
public uint16 padding;
public uint32 size;
[CCode (delegate_target = false, type = "void*")]
public weak AudioCallback callback;
public void* userdata;
}// AudioSpec
And then I can just create a function:
public static void callback(void* userdata, uchar* stream, int len)
And:
audiospec.callback = callback;
Ahhh, finally my beautiful white noise generator is complete!
I think it's a bug in the VAPI. In sdl.vapi, try changing
[Compact]
public class AudioSpec {
to
public struct AudioSpec {
and
[CCode (cname="SDL_OpenAudio")]
public static int open(AudioSpec desired, AudioSpec obtained);
to
[CCode (cname="SDL_OpenAudio")]
public static int open(AudioSpec desired, out AudioSpec obtained);
and make your code look like:
AudioSpec audiospec = AudioSpec();
AudioSpec specback;
audiospec.freq = 22050;
audiospec.format = SDL.AudioFormat.S16LSB;
audiospec.channels = 2;
audiospec.samples = 512;
// try to initialize sound with these values
if (SDL.Audio.open(audiospec, out specback) < 0)
{
stdout.printf("ERROR! Check audio settings!\n");
return 1;
}
and give it a test. It seems to generate the correct code according to the SDL docs. If it works, consider submitting the VAPI changes to the Vala bugzilla.
Okay, the delegate:
public delegate void AudioCallback (out void* userdata, out uchar stream, int len);
has the C type:
void(*AudioCallback)(void**userdata, unsigned char* stream, int len);
where userdata and stream are write-only, which is not really what you want.
void (*callback)(void *userdata, Uint8 *stream, int len);
In this, userdata is just a pointer to some stuff for your use. In Vala's terms, it's the target of a delegate. stream is an array, but SDL has allocated it, so it's not out and len is the length of the array, so we can have Vala deal with that automatically with just uint8[] stream. Putting it all together:
[CCode(instance_pos = 0)]
public delegate void AudioCallback(uint8[] stream);
The instance_pos tells Vala where the userdata is. It normally assumes it to be last. As for the struct:
[CCode (cname="SDL_AudioSpec", destroy_function = "")]
public struct AudioSpec {
...
[CCode(delegate_target_cname = "userdata")]
public AudioCallback callback;
}
This will create a callback that stores the target in userdata. Now, to avoid leaking memory, Vala is going to try to assign a destructor to callback_target_destroy_notify...and now we're stuck because we have no member for that. So, let's back up and try again:
[CCode(has_target = false)]
public delegate void AudioCallback(void* userdata, uint8[] stream);
The has_target tells Vala there is no userdata and we include it manually. As for the struct:
[CCode (cname="SDL_AudioSpec", destroy_function = "")]
public struct AudioSpec {
...
public AudioCallback callback;
public void* userdata;
}
So, userdata will get passed to your callback, but you'll have to cast it yourself and you'll have to manage the memory. Additionally, when the structs go out of scope, Vala is going to call a destroy function. By specifying an empty string, it will do nothing. Normally, this frees memory inside the struct, but we don't need to worry here.