От родного C ++ до управляемого C ++ до C # - PullRequest
0 голосов
/ 15 июля 2009

Я работаю над переносом большого количества файлов .h и .lib из собственного C ++ в Managed C ++ для последующего использования в качестве ссылочного .dll в C #.

Пожалуйста, я знаю, что было бы намного проще перенести все это на .NET, но если бы я мог, я бы это сделал. Это сторонний разработчик, и у меня есть только файлы .lib (без экспорта) и .h для работы.

Все шло гладко, пока я не включил виртуальные функции, и теперь у меня возникли некоторые проблемы с делегатами.

Среди ошибок, которые я получаю:

ошибка C3756: «ThreadFunc»: определение делегата конфликтует с существующим символом
ошибка C2079: «MyWrapTest :: MyThreadWrap :: m_threadAttr» использует неопределенный класс «MyWrapTest :: MyThreadAttrWrap» ошибка C2664: «MyWrapTest :: AutoPtr :: AutoPtr (T *)»: невозможно преобразовать параметр 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;
};
}

Ответы [ 2 ]

0 голосов
/ 15 июля 2009

Евгений

Спасибо за ввод. Должен любить усталые глаза после долгого дня. Вы были правы, когда AutoPtr объявил неверный тип.

Что касается "теневой копии" собственного объекта потока, я действительно следовал хорошо документированной практике, рекомендованной Microsoft для обеспечения правильного управления собственным объектом в .NET.

MSDN Артикул

Вопрос делегата был также связан с усталыми глазами. Мне нужно было изменить имя делегата, чтобы существующая (нативная) функция существовала в том же пространстве, что и новый делегат.

У меня все еще есть проблема с предварительными декларациями, но я уверен, что скоро смогу это исправить.

0 голосов
/ 15 июля 2009

Почему вы снова определяете 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 что-то путает)

Вам нужно инициализировать m_NativeMyThread с новым объектом MyThread, который был создан с неуправляемым объектом MyThreadAttr *, который был извлечен из MyThreadAttrWrap, который был передан вашему конструктору.

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

Кстати, будьте очень осторожны с владением. Из кода, который вы разместили, неясно, принадлежит ли MyThread MyThreadAttr или принадлежит ему извне. А AutoPtr владеет своим указателем (если он вообще назван правильно).

...