views:

654

answers:

2

I am working on porting a large number of .h and .lib files from native C++ to Managed C++ for eventual use as a referenced .dll in C#.

Please, I know it'd be a lot easier to port the whole thing to .NET, but if I could I would. It's 3rd party and all I have are .lib(no exports) and .h files to work with.

Everything has been going smoothly until I hit virtual functions and now I'm having some delegate issues.

Among the errors I'm getting are: error C3756: 'ThreadFunc': delegate definition conflicts with an existing symbol
error C2079: 'MyWrapTest::MyThreadWrap::m_threadAttr' uses undefined class 'MyWrapTest::MyThreadAttrWrap' error C2664: 'MyWrapTest::AutoPtr::AutoPtr(T *)' : cannot convert parameter 1 from 'MyWrapTest::MyThreadAttrWrap' to 'MyThread *'

For clarity, I'll include the native code and the stuff I'm working on now. First, native code:

#ifndef MYTHREAD_HPP
#define MYTHREAD_HPP

#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
#define STDCALL unsigned __stdcall
typedef unsigned (__stdcall *ThreadFunc)(void*);
#else
#define STDCALL void*
typedef void* (*ThreadFunc)(void*);
typedef unsigned int HANDLE ;
#endif
#include "generaltypes.hpp"

class MyThreadAttr;

class MyThread
{
public:
    MyThread(void);
    MyThread(MyThreadAttr * tta);
    virtual ~MyThread() {};
    virtual HANDLE start(ThreadFunc,void *, unsigned *);
    virtual int stop();
    static void wait(HANDLE);
#ifdef WIN32
    static void wait(HANDLE, int);// msec timeout required since 'cancelThread' is no-op  
#endif                            
    static void sleep(unsigned int);
    static int32 cancelThread(HANDLE hThread);  // no-op on Windows (returns -1)!
#ifndef WIN32
    static void setCancelStates(void);
    static void endProcess(); 
#endif

protected:
  MyThreadAttr * m_threadAttr;
  void setThreadAttr(MyThreadAttr * tta);


private:

};

#endif

AND THE NEW STUFF I'M DEVELOPING:

#pragma once

#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
#define STDCALL unsigned __stdcall
//typedef unsigned (__stdcall ThreadFunc)(Object^);
#else
#define STDCALL Object^
typedef unsigned int HANDLE;
#endif
#include "gentypes.hpp"
#include "AutoPtr.h"
#include "MyThread.hpp"

using namespace System;
using namespace System::Runtime::InteropServices;

namespace MyWrapTest
{

public delegate Object^ ThreadFunc(Object^ o);

ref class MyThreadAttrWrap;
//#include "MyThreadAttrWrap.h"

public ref class MyThreadWrap
{
public:
    MyThreadWrap(void)
    {
     AutoPtr<MyThread> m_NativeMyThread(new MyThread);
    };
    MyThreadWrap(MyThreadAttrWrap tta)
    {
     AutoPtr<MyThread> m_NativeMyThread(tta);
    };
    /*virtual ~MyThreadWrap(){};
    virtual HANDLE start(ThreadFunc,System::Object^, unsigned ^);
    virtual int stop();*/
    static void wait(HANDLE h)
    {
     m_NativeMyThread->wait(h);
    };
#ifdef WIN32
    static void wait(HANDLE h, int i) // msec timeout required since 'cancelThread' is no-op  
    {
     m_NativeMyThread->wait(h, i);
    };
#endif                            
    static void sleep(unsigned int i)
    {
     m_NativeMyThread->sleep(i);
    };
    static int32 cancelThread(HANDLE hThread);  // no-op on Windows (returns -1)!
#ifndef WIN32
    static void setCancelStates(void);
    static void endProcess(); 
#endif

protected:
  MyThreadAttrWrap m_threadAttr;
  void setThreadAttr(MyThreadAttrWrap tta);


private:
    AutoPtr<MyThread> m_NativeMyThread;
};
}

Any help would be gratefully appreciated!

A: 

Why do you define m_NativeMyThread in constructors again -- this makes it local variable, you probably want this:

MyThreadWrap()
    : m_NativeMyThread(new MyThread)
{
};

Or

MyThreadWrap()
{
    m_NativeMyThread = AutoPtr<MyThread>(new MyThread);
};

I don't usually use .Net, so I'm not sure about semantics of AutoPtr, but you want to change your member object, not create a local shadow.

As for the error, here you create new local object of type AutoPtr and pass it one argument of type MyThreadAttrWrap. MyThreadWrap(MyThreadAttrWrap tta) { AutoPtr m_NativeMyThread(tta); }; (I'm reading it as C++, correct me if .Net confuses things)

What you want is to initialize m_NativeMyThread with new MyThread object that was constructed with unmanaged MyThreadAttr* object that was extracted from MyThreadAttrWrap that was passed in to your constructor.

MyThreadWrap(MyThreadAttrWrap tta)
{
    m_NativeMyThread = AutoPtr<MyThread>(new MyThread(tta.GetNativeAttr()));
};

BTW, be very carefull with ownership. From code you posted it is unclear if MyThread owns MyThreadAttr or if it is owned externally. And AutoPtr owns its enclosed pointer (if it at all named properly).

Eugene
A: 

Eugene,

Thanks for the input. Gotta love tired eyes after a long day. You were right on with the AutoPtr declaring the wrong type.

As for the "shadow copy" of the native thread object, I was really following a well-documented practice recommended by Microsoft for making sure the native object management is done correctly in .NET.

MSDN Article

The delegate issue was related to tired eyes as well. I needed to change the Delegate Name to allow the existing(native) function to exist in the same space as the new delegate.

I am still having some issue with forward declarations, but I'm sure I can clear that up soon.

TomO