2009-07-14 19 views
0

Ich arbeite an der Portierung einer großen Anzahl von .h und .lib-Dateien von systemeigenem C++ zu verwaltetem C++ für die eventuelle Verwendung als eine referenzierte DLL in C#.Natives C++ zu verwaltetes C++ zu C#

Bitte, ich weiß, es wäre viel einfacher, das Ganze nach .NET zu portieren, aber wenn ich könnte, würde ich es tun. Es ist 3rd Party und alles was ich habe sind .lib (keine Exporte) und .h Dateien um damit zu arbeiten.

Alles lief glatt, bis ich virtuelle Funktionen traf und jetzt einige delegierte Probleme habe.

Unter den Fehler Ich erhalte sind:

C3756 Fehler: 'ThreadFunc': Definition Konflikte mit einem vorhandenen Symbol
Fehler C2079 delegieren: 'MyWrapTest :: MyThreadWrap :: m_threadAttr' undefined Klasse verwendet 'MyWrapTest :: MyThreadAttrWrap' Fehler C2664: 'MyWrapTest :: AutoPtr :: AutoPtr (T *)': kann nicht Parameter konvertieren 1 von 'MyWrapTest :: MyThreadAttrWrap' auf 'MyThread *'

aus Gründen der Klarheit I werde den nativen Code und die Sachen, an denen ich arbeite, nicht enthalten w. Zuerst nativen 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); 
}; 

#endif 

UND DAS NEUE STUFF Ich entwickle:

#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; 
}; 
} 
+0

Markieren Sie Ihren gesamten Code und drücken Sie die Taste 0101 oben im Menü. – jkeys

Antwort

0

Warum Sie m_NativeMyThread in Konstrukteuren wieder definieren tun - das macht es lokale Variable, werden Sie wahrscheinlich diese wollen:

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

Oder

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

Normalerweise verwende ich .Net nicht, daher bin ich mir nicht sicher über die Semantik von AutoPtr, aber Sie möchten Ihr Member-Objekt ändern und keinen lokalen Schatten erstellen.

Für den Fehler, hier erstellen Sie neues lokales Objekt vom Typ AutoPtr und übergeben Sie ein Argument vom Typ MyThreadAttrWrap. MyThreadWrap (MeinThreadAttrWrap tta) { AutoPtr m_NativeMyThread (tta); }; (lese ich es wie C++, korrigieren Sie mich, wenn .Net Dinge verwechselt)

Was Sie wollen, ist m_NativeMyThread mit neuen MyThread Objekt zu initialisieren, die mit nicht verwalteten MyThreadAttr * Objekt konstruiert wurde, die aus MyThreadAttrWrap extrahiert wurde, die übergeben wurde zu Ihrem Konstruktor.

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

BTW, seien Sie sehr vorsichtig mit dem Besitz. Aus dem Code, den Sie gepostet haben, ist unklar, ob MyThread MyThreadAttr besitzt oder ob es extern gehört. Und AutoPtr besitzt seinen eingeschlossenen Zeiger (wenn er überhaupt richtig benannt wurde).

0

Eugene,

Danke für die Eingabe. Muss müde Augen nach einem langen Tag lieben. Du warst direkt mit der AutoPtr, die den falschen Typ deklarierte.

Was die "Schattenkopie" des nativen Thread-Objekts betrifft, folgte ich wirklich einer gut dokumentierten Praxis, die von Microsoft empfohlen wurde, um sicherzustellen, dass die native Objektverwaltung in .NET korrekt durchgeführt wird.

MSDN Article

Der Delegierte Problem wurde auch zu müde Augen zusammen. Ich musste den Delegiertennamen ändern, damit die vorhandene (native) Funktion im selben Bereich wie der neue Delegat vorhanden ist.

Ich habe immer noch ein Problem mit Vorwärtsdeklarationen, aber ich bin mir sicher, dass ich das bald klären kann.