0

我正在将大量 .h 和 .lib 文件从本机 C++ 移植到托管 C++ 以最终用作 C# 中的引用 .dll。

拜托,我知道将整个东西移植到 .NET 会容易得多,但如果可以的话,我会的。这是第 3 方,我只有 .lib(无导出)和 .h 文件可以使用。

一切都很顺利,直到我遇到了虚拟功能,现在我遇到了一些委托问题。

我遇到的错误包括:

错误 C3756:“ThreadFunc”:委托定义与现有符号冲突
错误 C2079:“MyWrapTest::MyThreadWrap::m_threadAttr”使用未定义的类“MyWrapTest::MyThreadAttrWrap” ' : 无法将参数 1 从 'MyWrapTest::MyThreadAttrWrap' 转换为 'MyThread *'

为了清楚起见,我将包括本机代码和我现在正在处理的东西。一、原生代码:

#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

以及我正在开发的新东西:

#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;
};
}
4

2 回答 2

0

你为什么要在构造函数中再次定义 m_NativeMyThread ——这使它成为局部变量,你可能想要这个:

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

或者

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

我通常不使用 .Net,所以我不确定 AutoPtr 的语义,但您想更改您的成员对象,而不是创建本地阴影。

至于错误,在这里您创建了 AutoPtr 类型的新本地对象,并将一个 MyThreadAttrWrap 类型的参数传递给它。MyThreadWrap(MyThreadAttrWrap tta) { AutoPtr m_NativeMyThread(tta); }; (我将它读为 C++,如果 .Net 混淆了,请纠正我)

您想要的是使用新的 MyThread 对象初始化 m_NativeMyThread,该对象是使用从传递给构造函数的 MyThreadAttrWrap 中提取的非托管 MyThreadAttr* 对象构造的。

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

顺便说一句,要非常小心所有权。从您发布的代码中,不清楚 MyThread 是否拥有 MyThreadAttr 或者它是否由外部拥有。并且 AutoPtr 拥有其封闭的指针(如果它完全命名正确的话)。

于 2009-07-15T00:21:07.203 回答
0

尤金,

感谢您的输入。经过漫长的一天后,一定要爱上疲惫的眼睛。您正确地使用 AutoPtr 声明了错误的类型。

至于本机线程对象的“影子副本”,我确实遵循了 Microsoft 推荐的有据可查的做法,以确保在 .NET 中正确完成本机对象管理。

MSDN 文章

代表问题也与眼睛疲劳有关。我需要更改委托名称以允许现有(本机)函数与新委托存在于同一空间中。

我仍然对前向声明有一些问题,但我相信我很快就能解决这个问题。

于 2009-07-15T14:34:30.957 回答