Server Help

Non-Subspace Related Coding - C++ : Inheritance,Template and Threads problems

Samapico - Mon Sep 28, 2009 1:28 am
Post subject: C++ : Inheritance,Template and Threads problems
I have a class (Layer) from which another class (Layer_net) inherits. Other classes will inherit from it eventually.
I made the Layer class a template because there is a specific data type that I want to specify for each child class.
I'm having problems to define class functions outside the class body. They compile fine, but the linker freaks out when one of the function appears in the code.

Code: Show/Hide
#define T_LAYER template <typename T>

T_LAYER
class Layer
{
public:
//stuff...
void Func1();
void Func2() { printf("hi, this is Func2\n"); }
};

T_LAYER
void Layer<T>::Func1()
{
   printf("hi, this is Func1\n");
}




//meanwhile, in another class not far away...

struct HeaderNetwork
{
   char ip[4];
};

class Layer_net : public Layer<HeaderNetwork>
{
public:
   //stuff
};



//and in the main...

int main(void)
{
   Layer_net net;

   net.Func1();
   net.Func2();
}

Ok, it seems the above code works if you put it all in the same file.

I then split it up in a header file and 2 cpp's like so:

header.h
Code: Show/Hide

#include <stdio.h>
#include <stdlib.h>

struct HeaderNetwork
{
   char ip[4];
};


template <typename T>
class Layer
{
public:

   //stuff...
   void Func1(int);
   void Func2() { printf("hi, this is Func2\n"); }
};



//meanwhile, in another class not far away...

class Layer_net : public Layer<HeaderNetwork>
{
public:
   //stuff
};



layer.cpp
Code: Show/Hide

#include <stdio.h>
#include <stdlib.h>


#include "header.h"

template <typename T>
void Layer<T>::Func1(int a)
{
   printf("hi, this is Func1\n");
}


main.cpp
Code: Show/Hide

#include "header.h"

//and in the main...

int main(void)
{
   Layer_net net;

   net.Func1(1);
   net.Func2();

   getchar();
}


Build results:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>Generating Code...
1>Compiling...
1>layer.cpp
1>Generating Code...
1>Linking...
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layer<struct HeaderNetwork>::Func1(int)" (?Func1@?$Layer@UHeaderNetwork@@@@QAEXH@Z) referenced in function _main
1>D:\Sam\Prog Projects\GPA785\trunk\Debug\test.exe : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://d:\Sam\Prog Projects\GPA785\trunk\test\Debug\BuildLog.htm"
1>test - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Can anyone figure out what's happening?
Using Visual Studio 2005
Samapico - Mon Sep 28, 2009 2:00 am
Post subject:
I think I found my answer

http://cpp.developpez.com/faq/cpp/?page=templates#DIVERS_templates
(in french)

Basically, for some reason I have to make the layer.cpp NOT compile, and instead of including the header in it, I must include the cpp at the end of the header file...


I don't really understand why, but it works tongue.gif
Samapico - Mon Sep 28, 2009 2:21 am
Post subject:
I have another somewhat related problem, and I'm pretty tired now, so excuse me if it's dumb:


Still in my template class, I got some function declared:

DWORD WINAPI threadloop(LPVOID iValue);

and defined later.
And then I want to create a thread in there...

First try:
Code: Show/Hide
hthread = CreateThread(NULL, 0, threadloop, "", 0, &threadID);   
error C3867: 'Layer<T>::threadloop': function call missing argument list; use '&Layer<T>::threadloop' to create a pointer to member

Ok... second try:
Code: Show/Hide
hthread = CreateThread(NULL, 0, &Layer<T>::threadloop, "", 0, &threadID);   
error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (__stdcall Layer<T>::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE'

And then I desperately tried to typecast it:
Code: Show/Hide
hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&Layer<T>::threadloop), "", 0, &threadID);


It failed.
A lot of stuff in there looks weird to me, but I started from an example given by the teacher... but yeah, he wasn't using templates, obviously tongue.gif
Doc Flabby - Mon Sep 28, 2009 5:05 am
Post subject:
I recommend looking at pthreads icon_smile.gif or using a C++ framework. Working directly with the Windows API is a PITA but anyways:

Code: Show/Hide

hthread = CreateThread(NULL, 0, &Layer<T>::threadloop, "", 0, &threadID);


The problem here is the compiler does not know what T is. Creating an instance of the class Layer<T> and pass it to the function might fix this problem.

eg,
Code: Show/Hide

Layer<int> t = new Layer<int>;
hthread = CreateThread(NULL, 0, &t::threadloop, "", 0, &threadID);


This might not work btw tongue.gif

I'm not overally familier with templates (i've not used them) in C++ but this link might help http://docs.google.com/gview?a=v&q=cache:twJe98TSVCIJ:www.allankelly.net/static/writing/overload/Threads/ThreadTemplate.pdf+templates+theading&hl=en&gl=uk&sig=AFQjCNEN1kd0XAxuQ2BA4Gq6xtyPrEfVsA[/code]
Samapico - Mon Sep 28, 2009 10:21 am
Post subject:
hmmm, the CreateThread call is from the Layer class itself as well, so it should know what T is icon_surprised.gif

Code: Show/Hide
T_LAYER
void Layer<T>::Start(void)
{
   if (hthread == NULL)
   {
      run_thread = true;
      hthread = CreateThread(NULL, 0, threadloop, "", 0, &threadID);   
   }
}


Your suggestion doesn't work, I also tried with this->
Doc Flabby - Mon Sep 28, 2009 10:44 am
Post subject:
You would think it would, but it is C++ after all tongue.gif

I found the source for that link which has threads created inside Templates (go to bottom of the page)

http://www.allankelly.net/writing/softdesign.html
http://www.allankelly.net/static/writing/overload/Threads/threadssource.zip

From the source (snippit) you can see its a bit of a hack job tongue.gif Essentially you have to pass the RunThread an object that implements a "run" function (this might sound familier tongue.gif)
Code: Show/Hide

   void RunThread(   T      &x,
               long   stackSize = 0)
   {
      // each object represents one thread
      // therefore, should not launch multiple threads with one object
      assert (NULL == m_threadHandle);

      // other parameters may be dafaulted if needed
      DWORD dwStack = (DWORD) stackSize;

      // create a  thread
      m_threadHandle = CreateThread( 
                        NULL,         // pointer to thread security attributes 
                        dwStack,      // initial thread stack size, in bytes
                        StartRun,      // pointer to thread function 
                        &x,            // argument for new thread
                        0,            // creation flags
                        &m_threadId);   // pointer to returned thread identifier
      DWORD last = GetLastError();   // useful for debug stepping

      if (NULL == m_threadHandle)
      {
         throw std::runtime_error("Failed to start thread");
      }
   }

static unsigned long __stdcall StartRun(void *param)
   {   
      T* object = static_cast<T*> (param);   // reclaim object type
      object->Run();
      return 0;
   }

Samapico - Mon Sep 28, 2009 7:10 pm
Post subject:
hmmmm, but the argument of RunThread would still have to be of type Layer<T>, since I want the Run() function to be in there

Not sure how to translate this in my project...
Dr Brain - Mon Sep 28, 2009 7:32 pm
Post subject:
This is why C++ always seems horrible to me. Simple, easy things are complicated and non-intuitive. You use it if you have to, but stay away from it otherwise.
Samapico - Mon Sep 28, 2009 10:54 pm
Post subject:
I could go the easy way and get rid of the template, that would just give me some copy paste to do
Samapico - Thu Oct 01, 2009 11:57 am
Post subject:
Samapico wrote:
I could go the easy way and get rid of the template, that would just give me some copy paste to do
Oh well... I went the easy way tongue.gif
I didn't actually need the members of the type in the base class, I only needed to know the sizeof it to allocate memory and such. So I just used an int for the size, and initialize it to sizeof(MyHeader) in the derived class.

F*** templates.
All times are -5 GMT
View topic
Powered by phpBB 2.0 .0.11 © 2001 phpBB Group