I'm having a problem with SDL threads so I made a little multi file code so it will be easier to show my problem
Header file
#ifndef MAINC_H_INCLUDED
#define MAINC_H_INCLUDED
#include <iostream>
#include <CONIO.H>
#include <SDL.h>
#include <SDL_thread.h>
using namespace std;
class mainc
{
private:
SDL_Thread* thread;
int threadR;
int testN=10;
public:
int threadF(void *ptr);
int OnExecute();
bool start();
};
#endif
One file
#include "mainc.h"
bool mainc::start() {
if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return false;
}
getch();
if(SDL_CreateThread(threadF, "TestThread", (void *)NULL)==NULL){
return false;
}
return true;
}
int mainc::threadF(void *ptr){
cout<<"This is a thread and here is a number: "<<testN<<endl;
return testN;
}
Second file
#include "mainc.h"
int mainc::OnExecute() {
if(!start())
{
return -1;
}
SDL_WaitThread(thread,&threadR);
return 0;
}
int main(int argc, char* argv[]) {
mainc game;
return game.OnExecute();
}
When I compile this I get this error
cannot convert 'mainc::threadF' from type 'int (mainc::)(void*)' to type 'SDL_ThreadFunction {aka int (*)(void*)}'
I dug around a bit and I found a solution but it gave me other errors I needed to make threadF static but I couldn't access any variables it gave me this error
invalid use of member 'mainc::testN' in static member function
But if I remove the variable from the function it runs fine
Now I don't know what do to because in my game I need to share variables which change
testN is neither a static nor a public property of class mainc and to do what you're trying to do, it needs to be either.
If you want to use members of class "mainc" from within another thread body, you need to pass a pointer to an object of class "mainc" to SDL_CreateThread:
// ...
SDL_CreateThread(threadF, "TestThread", this)
// ...
and then
int mainc::threadF(void *ptr)
{
mainc* myMainc = (mainc*)ptr;
myMainc->testN; // now you can use it as you need
}
Beware of the encapsulation, though (testN is actually private)
Related
The code should explain my difficulty. Though the code itself is quite meaningless, I'm planning to add containers in MyClass, and use algorithms with member functions.
#include <cstdlib>
#include <algorithm>
#include <functional>
using namespace std;
class MyClass
{
public:
MyClass() { a = 0; }
~MyClass() {}
private:
int a;
bool tiny_test (int);
int Func();
};
bool MyClass::tiny_test (int b)
{
return a == b;
}
int MyClass::Func()
{
// does not compile
(mem_fun(&MyClass::tiny_test))(this);
// commented below is another attempt, also no success
//mem_fun1_t<bool, MyClass, int> tmp_functor = mem_fun(&MyClass::tiny_test);
//tmp_functor(this);
return 0;
}
int main(int argc, char** argv)
{
return 0;
}
Thanks a lot! Btw, I'm not using a static member function, simply because I believe it must work for non-static member functions.
P.S. Eric, Jarod42, thanks for prompt replies!
bool MyClass::tiny_test (int b)
{ // ^^^^^ You missed this argument
return a == b;
}
Try this:
// Supply one more argument. E.g., 3
(mem_fun(&MyClass::tiny_test))(this, 3);
What this code do:
Several commands executed to completion(if(current seconds == some seconds) stop).
CommandProcessor(functor) run this commands. Pointer of this class I try to throw to pthread_create.
The question:
It is possible to use class object as callable?
command.h
#ifndef COMMAND_H
#define COMMAND_H
#include <iostream>
#include "commandprocessor.h"
class CommandProcessor;
using namespace std;
class Command
{
static CommandProcessor *commandProcessor;
time_t stopSeconds;
public:
Command(int _stopSeconds);
static void setProcessor(CommandProcessor *_commandProcessor);
void execute();
};
#endif // COMMAND_H
command.cpp
#include "command.h"
CommandProcessor* Command::commandProcessor = NULL;
Command::Command(int _stopSeconds)
{
stopSeconds = _stopSeconds;
}
void Command::setProcessor(CommandProcessor *_commandProcessor)
{
commandProcessor = _commandProcessor;
}
void Command::execute()
{
time_t seconds;
time_t now = time(NULL);
seconds = localtime(&now)->tm_sec;
cout << seconds << endl;
if(seconds != stopSeconds)
commandProcessor->addCommand(this);
}
commandprocessor.h
#ifndef COMMANDPROCESSOR_H
#define COMMANDPROCESSOR_H
#include <list>
#include "command.h"
using namespace std;
class Command;
class CommandProcessor
{
list< Command* > commandsList;
public:
void addCommand(Command *_command);
void operator()();
};
#endif // COMMANDPROCESSOR_H
commandprocessor.cpp
#include "commandprocessor.h"
void CommandProcessor::addCommand(Command *_command)
{
commandsList.push_back(_command);
}
void CommandProcessor::operator()()
{
while(commandsList.size() > 0)
{
Command *command = commandsList.front();
commandsList.pop_front();
command->execute();
}
}
main.cpp
#include <iostream>
#include <pthread.h>
#include "commandprocessor.h"
#define MAX_THREADS 2
using namespace std;
int main(int argc, char **args)
{
CommandProcessor *processor = new CommandProcessor();
Command::setProcessor(processor);
processor->addCommand(new Command(53));
processor->addCommand(new Command(24));
processor->addCommand(new Command(15));
pthread_t threads[MAX_THREADS];
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor(), NULL); // error: 'processor' cannot be used as a function
}
return 0;
}
DISCLAIMER : this is the kind of thing that you really shouldn't be doing in C++, as it includes messing around with void*. It needs to be used here because of the interaction with the C API. If you can, use std::thread from C++11 or boost::thread if you're using an older compiler.
To answer your question : yes, it is perfectly fine to make a class object as a callable (as a "function") once you implement operator() for it. You already did that, but the problem is the extra code needed to implement the interface between C++ and the C API for Pthreads.
The main reason why you're getting the "processor cannot be used as a function" error here is because processor is a CommandProcessor* and, as such, needs a dereference. However, even doing (*processor)() wouldn't help you, because pthread_create is defined as follows :
int pthread_create(phread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
This means that the function to be executed must return void* and take a void*. The documentation also states that the parameter of start_routine has the value of arg originally given to the respective call to pthread_create.
However, you cannot pass a pointer to CommandProcessor::operator()() to pthread_create for a much more important reason : it is a member function. All non-static class member functions need to be called with an object so that they can refer to this inside their body.
The solution to your problem is to make a static function that will match the prototype required by pthread_create, and pass the pointer to a CommandProcessor as the arg of pthread_create. Have a look at this :
static void* processor_executor(void *arg)
{
CommandProcessor *processor = static_cast<CommandProcessor*>(arg);
(*processor)();
return NULL;
}
int main(int argc, char **argv)
{
/* ... */
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor_executor, static_cast<void*> (processor));
}
/* ... */
}
This way, operator() is executed inside the thread created by pthread_create, using the same CommandProcessor object as the one in main().
Keep in mind that accessing the same data from within many parallel threads will lead to data races. Use mutexes, semaphores, or condition variables to protect the data from parallel access.
I have the following code in file tested.cpp:
#include <iostream>
using namespace std;
class tested {
private:
int x;
public:
tested(int x_inp) {
x = x_inp;
}
int getValue() {
return x;
}
};
I also have another file (called testing.cpp):
#include <cppunit/extensions/HelperMacros.h>
#include "tested.cpp"
class TestTested : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE(TestTested);
CPPUNIT_TEST(check_value);
CPPUNIT_TEST_SUITE_END();
public:
void check_value();
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestTested);
void TestTested::check_value() {
tested t(3);
int expected_val = t.getValue();
CPPUNIT_ASSERT_EQUAL(7, expected_val);
}
When I try to compile the testing.cpp file I get: undefined reference tomain'`. Well, this is because I do not have main (the entry point for the program). So, the compiler does not know how to start the execution of the code.
But what is not clear to me is how to execute the code in the testing.cpp. I tried to add:
int main() {
TestTested t();
return 1;
}
However, it does not print anything (and it is expected to return an error message since 3 is not equal to 7).
Does anybody know what is the correct way to run the unit test?
Since you are writing a cppunit test, why not looking at cppunit doc ? (http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html)
It tells you that the main sould be written like this :
#include <cppunit/ui/text/TestRunner.h>
#include "ExampleTestCase.h"
#include "ComplexNumberTest.h"
int main( int argc, char **argv) {
CppUnit::TextUi::TestRunner runner;
runner.addTest( ExampleTestCase::suite() );
runner.addTest( ComplexNumberTest::suite() );
runner.run();
return 0;
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).
I was trying to compile a simple Helloworld program for BADA but through command prompt.After compiling i ma getting the errors as
c:/Helloworld/src/Helloworld.cpp:12: error: prototype for 'Osp::App::Application HelloWorld::CreateInstance()' does not match any in class 'HelloWorld'
C:/Helloworld/inc/HelloWorld.h:21: error: candidate is: static Osp::App::Application* HelloWorld::CreateInstance()
could any body help that what needs to be done with it.
Thanks
Code for Helloworld.h
#ifndef __HELLOWORLD_H__
#define __HELLOWORLD_H__
#include <FBase.h>
#include <FGraphics.h>
#include <FLocales.h>
#include <FSystem.h>
#include <FApp.h>
using namespace Osp::Base;
using namespace Osp::Graphics;
using namespace Osp::Locales;
using namespace Osp::System;
using namespace Osp::App;
class HelloWorld :
public Application // must inherit from Application class
{
public:
// The application must have a factory method that creates an instance of the application.
static Application* CreateInstance(void);
public:
HelloWorld();
~HelloWorld();
public:
// The application must provide its name.
String GetAppName(void) const;
protected:
// The application must provide its ID.
AppId GetAppId(void) const;
AppSecret GetAppSecret(void) const;
public:
// This method is called when the application is initializing.
bool OnAppInitializing(AppRegistry& appRegistry);
// This method is called when the application is terminating.
bool OnAppTerminating(AppRegistry& appRegistry);
// Thie method is called when the application is brought to the foreground
void OnForeground(void);
// This method is called when the application is sent to the background.
void OnBackground(void);
// This method is called when the application has little available memory.
void OnLowMemory(void);
// This method is called when the device's battery level changes.
void OnBatteryLevelChanged(BatteryLevel batteryLevel);
};
#endif
Code for Helloworld.cpp
#include "HelloWorld.h"
HelloWorld::HelloWorld()
{
}
HelloWorld::~HelloWorld()
{
}
Application*
HelloWorld::CreateInstance(void)
{
// You can create the instance through another constructor.
return new HelloWorld();
}
String
HelloWorld::GetAppName(void) const
{
static String appName(L"HelloWorld");
return appName;
}
AppId
HelloWorld::GetAppId(void) const
{
static AppId appId(L"93bt1p123e");
return appId;
}
AppSecret
HelloWorld::GetAppSecret(void) const
{
static AppSecret appSecret(L"9C645DDBA19C71BAD1204DA4DAA7A0B9");
return appSecret;
}
bool
HelloWorld::OnAppInitializing(AppRegistry& appRegistry)
{
// TODO:
// Initialization including UI construction can be done here.
// Load the application's latest data, if necessary.
// If this method is successful, return true; otherwise, return false.
return true;
}
bool
HelloWorld::OnAppTerminating(AppRegistry& appRegistry)
{
// TODO:
// Deallocate or close any resources still alive.
// Save the application's current states, if applicable.
// If this method is successful, return true; otherwise, return false.
return true;
}
void
HelloWorld::OnForeground(void)
{
result r = E_SUCCESS;
Canvas* pCanvas = GetAppFrame()->GetCanvasN();
if(pCanvas == null)
return;
Font* pFont = new Font();
pFont->Construct(FONT_STYLE_PLAIN | FONT_STYLE_BOLD, 50);
pCanvas->SetFont(*pFont);
r = pCanvas->DrawText(Point(30, 30), GetAppName());
if (IsFailed(r))
{
AppLog("pCanvas->DrawText() failed.\n");
delete pCanvas;
return;
}
r = pCanvas->Show();
if (IsFailed(r))
{ AppLog("pCanvas->Show() failed.\n");
delete pCanvas;
return;
}
delete pCanvas;
}
void
HelloWorld::OnBackground(void)
{
}
void
HelloWorld::OnLowMemory(void)
{
// TODO:
// Deallocate as many resources as possible.
}
void
HelloWorld::OnBatteryLevelChanged(BatteryLevel batteryLevel)
{
// TODO:
// It is recommended that the application save its data,
// and terminate itself if the application consumes much battery
}
Code for Helloworldentry.cpp
/**
* OSP Application entry point(OspMain) introduced.
*/
#include <fapp.h>
#include "HelloWorld.h"
using namespace Osp::Base::Collection;
extern "C"
{
__declspec(dllexport) void OspMain(int hInstance, int argc, char *argv[]);
}
/**
* Entry function of OSP Application which is called by the operating system.
*/
extern "C" {
void OspMain(int hInstance, int argc, char *argv[])
{
AppLog("OspMain() Started. \n");
result r = E_SUCCESS;
ArrayList* pArgs = new ArrayList();
pArgs->Construct();
for (int i = 0; i < argc; i++)
{
String* pEachArg = new String(argv[i]);
pArgs->Add(*pEachArg);
}
r = Osp::App::Application::Execute(HelloWorld::CreateInstance, pArgs);
if (IsFailed(r))
{
AppLog("Application execution has failed.\n");
}
if (pArgs)
{
pArgs->RemoveAll(true);
delete pArgs;
}
AppLog("OspMain() Ended. \n");
}
}
The compiler is complaining that you have defined a method with this signature:
Osp::App::Application HelloWorld::CreateInstance()
whereas the HelloWorld class declares that its CreateInstance method has this signature:
Osp::App::Application* HelloWorld::CreateInstance()
Note the difference in the return type. The class definition says that the method with this name returns an Application pointer but you have implemented a method that returns an Application object.
In the future, please post code along with compiler errors. It's rarely possible to adequately explain compiler errors in isolation from the code that produced them. For example, I can't tell you which return type is correct in this case; I can only tell you that the return types don't match (which is exactly what the compiler already said).