How do I wrap CFtpFileFind example, in C++? - c++

Trying to wrap this short example in C++. (and its been a while since I did this).
int main(int argc, char* argv[])
{
//Objects
CFtpConnection* pConnect = NULL; //A pointer to a CFtpConnection object
ftpClient UploadExe; //ftpClient object
pConnect = UploadExe.Connect();
UploadExe.GetFiles(pConnect);
system("PAUSE");
return 0;
}
.h -
class ftpClient
{
public:
ftpClient();
CFtpConnection* Connect();
void GetFiles(CFtpConnection* pConnect);
};
.cpp -
//constructor
ftpClient::ftpClient()
{
}
CFtpConnection* ftpClient::Connect()
{
// create a session object to initialize WININET library
// Default parameters mean the access method in the registry
// (that is, set by the "Internet" icon in the Control Panel)
// will be used.
CInternetSession sess(_T("FTP"));
CFtpConnection* pConnect = NULL;
try
{
// Request a connection to ftp.microsoft.com. Default
// parameters mean that we'll try with username = ANONYMOUS
// and password set to the machine name # domain name
pConnect = sess.GetFtpConnection("localhost", "sysadmin", "ftp", 21, FALSE );
}
catch (CInternetException* pEx)
{
TCHAR sz[1024];
pEx->GetErrorMessage(sz, 1024);
printf("ERROR! %s\n", sz);
pEx->Delete();
}
// if the connection is open, close it MOVE INTO CLOSE FUNCTION
// if (pConnect != NULL)
// {
// pConnect->Close();
// delete pConnect;
// }
return pConnect;
}
void ftpClient::GetFiles(CFtpConnection* pConnect)
{
// use a file find object to enumerate files
CFtpFileFind finder(pConnect);
if (pConnect != NULL)
{
printf("ftpClient::GetFiles - pConnect NOT NULL");
}
// start looping
BOOL bWorking = finder.FindFile("*"); //<---ASSERT ERROR
// while (bWorking)
// {
// bWorking = finder.FindNextFile();
// printf("%s\n", (LPCTSTR) finder.GetFileURL());
// }
}
So basically separated the connection and file manipulation into 2 functions. The findFile() function is throwing the assert. (Stepping into the findFile() and it is specifically at the first ASSERT_VALID(m_pConnection) in inet.cpp. )
How does the way I am passing the arround CFtpConnection* pConnect look?
EDIT - Looks like CObject vfptr is overwritten (0X00000000) in the GetFiles() function.
Any help is appreciated. Thanks.

ANSWER:
This session object must be allocated in the Connection function, with a pointer
declared as a member function of the class. When creating the object within the function,
"CInternetSession sess(_T("MyProgram/1.0"));" the object/session will be terminated when the function exits, being thrown off the stack. When that happens, we can't use the pConnect pointer in other functions.
There is a hierarchy to WinInet objects, with session being the top. If session is gone nothing else can be used. Thus, we must use new to allocate the object in memory so that it sustains after this function exits.

I don't think there is any real value in having the ftpClient class return the CFTPConnection object out of Connect (unless i'm missing something that you intend?) - it should just have that as a Member variable, and GetFiles could use that member directly (Likewise you'd add the CInternetSession as a member of the class and avoid the problem you describe above when it goes out of scope.)
In that manner the ftpClient manages the lifetime of the CFTPConnection and can destroy it in its destructor.

Related

Arduino/C++ right way to use pointers

I have the following scenario in a program that was written in C ++ (Arduino):
Service.h
class Service
{
public:
Service(AsyncWebServer *server, FS *fs);
~Service();
void loop();
private:
AsyncWebServer *_server;
FS *_fs;
JsonObject *Settings;
void LoadSettings();
}
Service.cpp
Service::Service(AsyncWebServer *server, FS *fs) : _server(server), _fs(fs) { }
Service::LoadSettings(){
{
File configFile = _fs->open("data.json", "r");
DynamicJsonBuffer jsonBuffer;
JsonObject &root = jsonBuffer.parseObject(configFile);
Settings = &root;
configFile.close();
}
Service:loop() {
LoadSettings();
}
In a correct program, once the Settings property is set, it should hold the value throughout the lifecycle, however I need to call the LoadSettings() method all the time because the Settings property is losing the value when the program exits the method LoadSettings()
What is the right way to work with pointers and class properties? What do i need to do?
The thing what you are doing is creating a local object by parsing the object file and then leaving the function
DynamicJsonBuffer jsonBuffer; // declared locally
JsonObject& root = jsonBuffer.parseObject(configFile) // root local
creates root, a local reference, then you set Settings to point to address of that reference after leaving the function, jsonBuffer ceases to exist.
You should instead either declare jsonBuffer static or better, make it a member variable _jsonBuffer
Not sure why you need root, just write
Settings = &(_jsonBuffer.parseObject(configFile));
(maybe you should also rename Settings to _settings to have the same style as the other member variables).

Accessing members in a typedef map struct?

My question should be simple and I've spent that last few hours trying to get an answer to it by figuring it out on my own (and google-ing) answers and getting nowhere.
I've got the following in my header file:
Window.hpp
typedef struct {
SDL_Window* window = 0;
const char* title = 0;
int width;
int height;
int flags;
} m_windowStruct;
typedef std::map<std::string, m_windowStruct> m_windowMap;
m_windowMap windowMap; /* <-- Made this accessible */
and in my source file I've the following code:
Window.cpp
bool Window::createWindow(std::string id, const char* title, int width, int height, int flags) {
m_windowMap* windowMap;
m_windowStruct windowData;
windowData.window = SDL_CreateWindow("insert window creation info here");
if (!windowData.window) {
windowData.title = title;
windowData.width = width;
windowData.height = height;
windowData.flags = flags;
windowMap->insert(m_windowMap::value_type(id, &windowData));
SDL_LogInfo(INFO, "Window creation successful");
return true;
}
else {
return false;
}
};
Which works all fine and dandy... The problem I'm having is accessing the mapped struct members after.
For example if I want the instance of the primary window I'd want the following function:
/* Returns the window instance from the mapped struct */
SDL_Window* Window::getWindow(std::string id) {
m_windowMap::const_iterator keyValuePair = windowMap.find(id); /* <-- New error: Error: expression must have a class type */
if (keyValuePair == windowMap.end()) { /* <-- same error as just above */
return 0;
}
return keyValuePair->second.window; /* <-- Same error as just above */
};
I cannot for the life of me figure out how to access the second window member so that I can then give it to my renderer!
Any ideas?
I guess you want the windowMap being a global variable which is accessible across multiple source files (i.e., .cpp). Here are the changes you need to make,
In header file, replace the last line with extern m_windowMap* windowMap;. This makes variable accessible to all source files that include the header.
In your main function (or anywhere appropriate), add this line to initialize the map windowMap = new m_windowMap();
Remove m_windowMap* windowMap; in the Window::createWindow function, otherwise the re-declaration creates a new local m_windowMap and the rest of the function makes no effect to the global windowMap.
Lastly, since the global windowMap is a pointer, change .find() and .end() to ->find() and ->end() in the getWindow function.
If the windowMap is indeed a class member of Window, it is actually easier and cleaner.
From the code you originally posted, remove m_windowMap* windowMap; in the Window::createWindow function. Otherwise the insert goes to this newly created local map. Also, change ->insert to .insert as you did not declare windowMap as an pointer in the header.

C++ *LPCSTR weird scope error

I currently have a class called TextureObject. In the creation function I create the texture, and assign a LPCSTR in the class to a parameter given in the function. When I return that LPCSTR later, it returns in an unexpected manner.
Some type names and functions are from DirectX 11, just ignore them.
Code:
The h File:
class TextureObject
{
public:
ID3D11ShaderResourceView *pTexture;
LPCSTR GetFilename() const { return *FFilename; }
bool IsNotNull;
void CreateTexture(ID3D11Device &dev,LPCSTR Filename);
void ReCreate(ID3D11Device &dev);
void Release();
int relativeId;
private:
LPCSTR *FFilename;
};
The cpp file:
void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
D3DX11CreateShaderResourceViewFromFile(
&dev, // the Direct3D device
Filename, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = new LPCSTR(Filename);
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device &dev)
{
CreateTexture(dev, *FFilename);
}
When using vs 2012 debugger in the CreateTexture function, the Filename debugger values are:
0x0a06fed0 "C:\Users\Utilizador\Desktop\particle.png"
Which is perfect for me! When i assign the class's FFilename:
FFilename = new LPCSTR(Filename);
It's ok. When I check the value of FFilename within the scope of this function, it's the same value of the Filename. But when i use GetFilename, things start getting crazy:
= 0x0a06fed0 "îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþü =I.C"
Mmm, I just met you, and this is crazy, but... Here's my value. mKay?
Well, please help me. Thank You
You are not copying the string. You are copying the pointer. I think you probably wanted to copy the string, because you cannot guarantee the caller's pointer will still reference valid data at a later time.
LPCSTR is just a const char*. There's probably a corresponding windows call, but I would just use strdup to copy the string.
Define FFilename as LPCSTR:
LPCSTR FFilename;
And then:
void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
D3DX11CreateShaderResourceViewFromFile(
&dev, // the Direct3D device
Filename, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = strdup(Filename);
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device &dev)
{
CreateTexture(dev, FFilename);
}
Since you are using C++, you are free to use std::string instead, which will be cleaned up automatically when the object is destroyed.
When you create your pointer FFilename, you're initializing it with another pointer. That's not going to make a copy of the string, now you have two pointers pointing to the same thing. Presumably that thing is a temporary object, and when you go to look at it later it's no longer valid.
I'd suggest using std::string for this instead, it's much less error prone. The c_str method can get a LPCSTR at any time.
As marcin_j said, use std::[w]string. As for the line:
FFilename = new LPCSTR(Filename);
It just allocates 4 bytes for a pointer and initializes it to the filename string. It doesn't actually copy the string. So you can still use the string, but it is owned by whoever calls TextureObject::CreateTexture, and may be released while TextureObject is still referencing it.
Change the class to:
class TextureObject
{
public:
// ...all the same stuff as before...
private:
wstring FFilename; // it's better to store filenames as Unicode
};
And the methods to:
void TextureObject::CreateTexture(ID3D11Device* dev, const wstring& Filename)
{
D3DX11CreateShaderResourceViewFromFile(
dev, // the Direct3D device
Filename.c_str(), // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = Filename;
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device* dev)
{
CreateTexture(dev, FFilename.c_str());
}

V8 FunctionTemplate Class Instance

I have the following class:
class PluginManager
{
public:
Handle<Value> Register(const Arguments& args);
Handle<ObjectTemplate> GetObjectTemplate();
};
I want the Register method to be accessible from JavaScript. I add it to the global object like this:
PluginManager pluginManagerInstance;
global->Set(String::New("register"), FunctionTemplate::New(pluginManagerInstance.Register));
It throws the following error:
'PluginManager::Register': function
call missing argument list; use
'&PluginManager::Register' to create a
pointer to member
I tried to do that, but it doesn't work either. And it's not correct, because I want it to call the Register method of the pluginManagerInstance.
Except for making the Register method static or global, any ideas?
Thanks.
You're trying to bind two things at once: the instance and the method to invoke on it, and have it look like a function pointer. That unfortunately doesn't work in C++. You can only bind a pointer to a plain function or a static method. So image you add a static "RegisterCB" method and register it as the callback:
static Handle<Value> RegisterCB(const Arguments& args);
...FunctionTemplate::New(&PluginManager::RegisterCB)...
Now where do you get the pluginManagerInstance from? For this purpose, most callback-registration apis in V8 have an additional "data" parameter that will get passed back to the callback. So does FunctionTemplate::New. So you actually want to bind it like this:
...FunctionTemplate::New(&PluginManager::RegisterCB,
External::Wrap(pluginManagerInstance))...
The data is then available through args.Data() and you can delegate to the actual method:
return ((PluginManager*)External::Unwrap(args.Data())->Register(args);
This can surely be made a little easier with some macro.
You will likely need to make it static. Don't forget member functions take a hidden this parameter as the first argument. Because of this, they rarely work well as function pointer prototypes.
For an example take a look at the code in this tutorial. The same method mernst suggests above is used to send a pointer to this object, to the log function.
in header:
virtual void log(const string &str);
static Handle<Value> logCallback(const Arguments &args);
Local<FunctionTemplate> makeStaticCallableFunc(InvocationCallback func);
Local<External> classPtrToExternal();
////////////////////////////////////////////////////////////////////////
//
// Converts an External to a V8TutorialBase pointer. This assumes that the
// data inside the v8::External is a "this" pointer that was wrapped by
// makeStaticCallableFunc
//
// \parameter data Shoudld be v8::Arguments::Data()
//
// \return "this" pointer inside v8::Arguments::Data() on success, NULL otherwise
//
////////////////////////////////////////////////////////////////////////
template <typename T>
static T *externalToClassPtr(Local<Value> data)
{
if(data.IsEmpty())
cout<<"Data empty"<<endl;
else if(!data->IsExternal())
cout<<"Data not external"<<endl;
else
return static_cast<T *>(External::Unwrap(data));
//If function gets here, one of the checks above failed
return NULL;
}
implementation:
////////////////////////////////////////////////////////////////////////
//
// Wrap a callback function into a FunctionTemplate, providing the "this"
// pointer to the callback when v8 calls the callback func
//
// \parameter func Static callback to be used in FunctionTemplate
//
// \return Local<FunctionTemplate> containing func
//
////////////////////////////////////////////////////////////////////////
Local<FunctionTemplate> V8TutorialBase::makeStaticCallableFunc(InvocationCallback func)
{
HandleScope scope;
Local<FunctionTemplate> funcTemplate = FunctionTemplate::New(func, classPtrToExternal());
return scope.Close(funcTemplate);
}
////////////////////////////////////////////////////////////////////////
//
// Makes the "this" pointer be an external so that it can be accessed by
// the static callback functions
//
// \return Local<External> containing the "this" pointer
////////////////////////////////////////////////////////////////////////
Local<External> V8TutorialBase::classPtrToExternal()
{
HandleScope scope;
return scope.Close(External::New(reinterpret_cast<void *>(this)));
}
Handle<Value> V8TutorialBase::logCallback(const Arguments &args)
{
HandleScope scope;
.....
V8TutorialBase *objPtr = externalToClassPtr<V8TutorialBase>(args.Data());
String::Utf8Value val(Local<String>::Cast(args[0]));
objPtr->log(*val); // log is a non static member function
// or you can directly do anything that you would do in a member function using the objPtr
return v8::Null();
}
If you want to call that method, you have to add parentheses:
lobal->Set( String::New("register")
, FunctionTemplate::New(pluginManagerInstance.Register()) );
^^
If you want to take its address, you have to add a &:
lobal->Set( String::New("register")
, FunctionTemplate::New(&PluginManager::Register) );
^
(Which is exactly what the error message says.)

I am new to threads, What does this compile error mean?

Using C++.
pthread_t threads[STORAGE]; // 0-99
...
void run()
Error>>> int status = pthread_create(&threads[0], NULL, updateMessages, (void *) NULL);
if (status != 0)
{
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
...
void ClientHandler::updateMessages(void *)
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
...
Compile Error:
TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’
I can't figure out whats wrong.
Thanks in advance.
A pointer to a member function is different from a global function with the same signature since the member function needs an additional object on which it operates. Therefore pointers to these two types of functions are not compatible.
In this case this means that you cannot pass a member function pointer to pthread_create but only a pointer to a non-member (or static) function. A work around for this problem is to use the forth parameter of pthread_create to pass a pointer to a object to a global function which then calls the method of the passed object:
class ClientHandler {
public:
void updateMessages();
void run();
};
// Global function that will be the threads main function.
// It expects a pointer to a ClientHandler object.
extern "C"
void *CH_updateMessages(void *ch) {
// Call "real" main function
reinterpret_cast<ClientHandler*>(ch)->updateMessages();
return 0;
}
void ClientHandler::run() {
// Start thread and pass pointer to the current object
int status = pthread_create(&threads[0], NULL, CH_updateMessages, (void*)this);
...
}
It's nothing to do with threads, it's a normal C++ error, you're just passing an incompatible type of function pointer.
A function pointer is not the same as a member instance function pointer, even if their signature is the same; this is because there is an implicit reference to *this passed. You can't avoid this.
As pthread_create takes a free function, create a static function(is a free function) inside ClientHandler
static void Callback(void * this_pointer,int other_arg) {
ClientHandler* self = static_cast< ClientHandler*>(this_pointer);
self-> updateMessages(other_arg);
}
and call pthread_create as follows
pthread_create(&threads[0], NULL, &ClientHandler::Callback, (void *) pointer_to_ClientHandler,int other_arg);
That works because Callback is free function
YoLinux has a nice pthread tutorial that my help you in learning about threads.
As others have already said, the problem is that the signatures between the functions are different. Class member functions always have a "secret" extra parameter, the this pointer. So you can never pass a member function where a global function is expected. You can hack around this either with libraries such as Boost.Bind, or by making the function a static member of the class.
But the simplest, and most elegant solution is to use a different threading API.
Boost.Thread is a very nice threading library for C++ (pthreads is designed for C, and that's why it doesnt play well with C++ features such as class methods).
I'd recommend using that.
Your code could be rewritten as something like this:
class ClientHandler {
public:
ClientHandler(/* All the parameters you want to pass to the thread. Unlike pthreads you have complete type safety and can pass as many parameters to this constructor as you like */){...}
void operator()() // boost.thread calls operator() to run the thread, with no parameters. (Since all parameters were passed in the constructor and saved as member variables
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
// whatever arguments you want to pass to the thread can be stored here as member variables
};
boost::threead_group gr; // can store all your threads here, rather than being limited to your fixed-size array
gr.create_thread(ClientHandler(/* construct a ClientHandler object with the parameters you like*/));
You're passing a member function instead of a global, normal, one.
Just define:
void updateMessages(void *) {
static ClientHandler c;
// use c..
}