Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C++ Class to C#, в DLL 
:(
    Опции темы
FelikZ
  Дата 27.2.2007, 21:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Собственно возможно ли пренести существующий C++(не .NET!) класс который экспортируется из длл, в C# проект?
Например такой:
Код


class __declspec( dllimport ) MyClass
{
public:
   int MyFunc(char *pStr)
   {
        return strlen(pStr);
   }
}


Если нет, то почему и как это можно обойти. Спасибо!

Это сообщение отредактировал(а) FelikZ - 27.2.2007, 21:19


--------------------
user posted image
PM WWW ICQ Skype   Вверх
Dray
Дата 28.2.2007, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Материалист
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 7.10.2003
Где: г. Всеволожск

Репутация: нет
Всего: 6



FelikZ, Лучше всего обернуть класс в COM


--------------------
忍者

user posted image
PM MAIL   Вверх
mr.DUDA
Дата 28.2.2007, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Проще всего выставить наружу функции через _dllexport / [DllImport], и юзать их передавая указатель на объект через IntPtr.


--------------------
user posted image
PM MAIL WWW   Вверх
FelikZ
Дата 28.2.2007, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Цитата(Dray @  28.2.2007,  14:46 Найти цитируемый пост)
FelikZ, Лучше всего обернуть класс в COM 

Попробую почитать про COM спасибо


Цитата(mr.DUDA @  28.2.2007,  19:55 Найти цитируемый пост)
юзать их передавая указатель на объект через IntPtr

Всмысле описать под каждый метод класса, функцию, которой передавать указатель на объект этого класса и она будет вызывать методы?


--------------------
user posted image
PM WWW ICQ Skype   Вверх
mr.DUDA
Дата 28.2.2007, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Цитата(FelikZ @  28.2.2007,  19:50 Найти цитируемый пост)
Всмысле описать под каждый метод класса, функцию, которой передавать указатель на объект этого класса и она будет вызывать методы?

Всмысле выставить наружу (из длл) функции, которые будут принимать на входе параметры и указатель на объект этого класса. Естессно, где-то нужно будет создать этот объект - одна из функций будет это делать. У меня так работает C#-обёртка над Adobe XMP SDK, где вовсю используются C++ объекты.


--------------------
user posted image
PM MAIL WWW   Вверх
FelikZ
Дата 28.2.2007, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Спасибо за помощь! smile 


--------------------
user posted image
PM WWW ICQ Skype   Вверх
FelikZ
Дата 10.3.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Столкнулся с проблемой :(
Что-то не так со строками в C# проекте(см. ниже): 

вот код C++ функии в Dll:
Код


#define Export extern "C" __declspec( dllexport )

class CVirtualFolder
{
    //....
public:
//Функция в классе
HRESULT CVirtualFolder::CreateVF(TCHAR* strFilePath)   //TCHAR == wchar_t т.к компилю в UNICODE
{
    TCHAR* strFilePath2=strFilePath;
    if(_isvfopened)
    {DME("CVirtualFolder::Create: VFERR_ALREADYOPENED")return VFERR_ALREADYOPENED;}

    _vf=_tfsopen(strFilePath2,_T("w+b"),_SH_DENYNO);

    if(NULL == _vf)
    {DME("CVirtualFolder::Create: VFERR_ACCESSDENIED")return VFERR_ACCESSDENIED;}

    _vfh->dwId=VF_ID;
    _vfh->fVersion=_version;

    _vfftt->dwCRC = NULL;
    _vfftt->dwId = VF_FTT_ID;
    _vfftt->dwFTSize = NULL;
    _vfftt->dwObjectCount = NULL;

    _vfh->dwFTTSize=_sizevfftt;
    _vfh->dwFTТAddr=_sizevfh;

    if(1!=fwrite(_vfh,_sizevfh,1,_vf))
    {DME("CVirtualFolder::Create: VFERR_FILEERROR")return VFERR_FILEERROR;}

    if(1!=fwrite(_vfftt,_sizevfftt,1,_vf))
    {DME("CVirtualFolder::Create: VFERR_FILEERROR")return VFERR_FILEERROR;}

    _isvfopened=true;
    _tcscpy_s(_vfName,MAX_PATH, strFilePath2);

    return S_OK;
}
    //....
};

//Как посоветовал mr.DUDA функции:

//Работа с функциями из класса
Export HRESULT CVirtualFolder_CreateVF(void *pClass, TCHAR* strFilePath)
{
    if(pClass == NULL)
        return -1;
    CVirtualFolder *vf = reinterpret_cast<CVirtualFolder*>(pClass);
    return vf->CreateVF(strFilePath);
}

// {26CC5D09-C586-4ae0-A1CA-E4BB2DAB2E99}
static const GUID IID_VirtualFolder = 
{ 0x26cc5d09, 0xc586, 0x4ae0, { 0xa1, 0xca, 0xe4, 0xbb, 0x2d, 0xab, 0x2e, 0x99 } };

//Выделение памяти под класс (заделка под COM :) не ругать!)
Export HRESULT QueryInterface(const IID iid, void** pOut)
{
    if(iid == IID_VirtualFolder)
    {
        *pOut = new CVirtualFolder();
    }
    else
    {
        return -1;
    }
    return 0;
}

//Очистка
Export HRESULT ReleaseInterface(const IID iid, void** pIn)
{
    if(pIn == NULL)
        return -1;
    if(*pIn == NULL)
        return -1;
    if(iid == IID_VirtualFolder)
    {
        CVirtualFolder *fol =(CVirtualFolder*) *pIn;
        delete fol;
    }
    else
    {
        return -1;
    }
    *pIn = NULL;
    return 0;
}


Вот код в C#, собственно здесь и проблема:
Код

using System;
using System.Collections.Generic;
using System.Text;
using CoreLibrary;
using System.Collections;
using System.Runtime.InteropServices;

namespace TestCore
{
    class Program
    {
        static void Main(string[] args)
        {
            unsafe
            {
                void* mClass;
                if (CoreMiscFuncs.QueryInterface(CoreMiscFuncs.IID_VirtualFolder, &mClass) < 0)  //Работает
                {
                    Console.WriteLine("Query error!");
                    return;
                }


                string path = @"D:\лялятополя.vf";
                char[] s = UTF8Encoding.UTF8.GetChars(UTF8Encoding.Unicode.GetBytes(path.ToCharArray()));

                //if (VirtualFolder.CVirtualFolder_CreateVF(mClass, path.ToCharArray()) < 0)  //ПОЧЕМУ Так НЕ работает
                //{
                //    Console.WriteLine("CreateVF error!");
                //    return;
                //}
                if (VirtualFolder.CVirtualFolder_CreateVF(mClass, s) < 0)  //ПОЧЕМУ Так работает, хотя я использую в DLL Unicode?!
                                                                                                          //Ведь если я не ошибаюсь UTF8 это НЕ юникод?!
                {
                    Console.WriteLine("CreateVF error!");
                    return;
                }

                VirtualFolder.CVirtualFolder_Close(mClass, true); //Работает

                if (CoreMiscFuncs.ReleaseInterface(CoreMiscFuncs.IID_VirtualFolder, &mClass) < 0) //Работает
                {
                    Console.WriteLine("Release error!");
                    return;
                }
            }
        }
    }

    public class VirtualFolder
    {
//
//Функции для выделения памяти под CVirtualFolder и освобождения
//
// {26CC5D09-C586-4ae0-A1CA-E4BB2DAB2E99}
        public static readonly Guid IID_VirtualFolder = new Guid("{ 0x26cc5d09, 0xc586, 0x4ae0, { 0xa1, 0xca, 0xe4, 0xbb, 0x2d, 0xab, 0x2e, 0x99 } }");
#if DEBUG
        [DllImport("CoreLibraryd.dll")]
#else
        [DllImport("CoreLibrary.dll")]
#endif //DEBUG
        public unsafe extern static int QueryInterface(Guid iid, void** pOut);
//---------------------------------------------------------
#if DEBUG
        [DllImport("CoreLibraryd.dll")]
#else
        [DllImport("CoreLibrary.dll")]
#endif //DEBUG
        public unsafe extern static int ReleaseInterface(Guid iid, void** pOut); 
//
//Несколько функций для работы с классом CVirtualFolder
//
#if DEBUG
        [DllImport("CoreLibraryd.dll")]
#else
        [DllImport("CoreLibrary.dll")]
#endif //DEBUG
        public static extern unsafe int CVirtualFolder_CreateVF(void* pClass, char[]  strFilePath);
//---------------------------------------------------------
#if DEBUG
        [DllImport("CoreLibraryd.dll")]
#else
        [DllImport("CoreLibrary.dll")]
#endif //DEBUG
        public static extern unsafe void CVirtualFolder_Close(void* pClass, bool isSave);
    }
}



Добавлено @ 14:09 
Сорри забыл уточнить!
Дело в том, что код который отмечен как не работающий, создает рядом с DLL файл с названием "АБРАКАДАБРА"(образно), а рабочий создает "D:\лялялятополя.vf"!


--------------------
user posted image
PM WWW ICQ Skype   Вверх
mr.DUDA
Дата 10.3.2007, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



UTF8 - это юникод.


--------------------
user posted image
PM MAIL WWW   Вверх
FelikZ
Дата 10.3.2007, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Цитата(FelikZ @  10.3.2007,  14:03 Найти цитируемый пост)
 char[] s = UTF8Encoding.UTF8.GetChars(UTF8Encoding.Unicode.GetBytes(path.ToCharArray()));

ОК, тогда что делает эта строка такого, что все начинает работать?


--------------------
user posted image
PM WWW ICQ Skype   Вверх
mr.DUDA
Дата 10.3.2007, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Может, TCHAR в твоей длл воспринимает UTF8, а не UTF16 (тогда конверсия имеет смысл) ?


--------------------
user posted image
PM MAIL WWW   Вверх
FelikZ
Дата 10.3.2007, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



в DLL:

winnt.h
Код


//....

#ifndef _MAC //MAC?
typedef wchar_t WCHAR;    // wc,   16-bit UNICODE character
#else
// some Macintosh compilers don't define wchar_t in a convenient location, or define it as a char
typedef unsigned short WCHAR;    // wc,   16-bit UNICODE character
#endif

//....

#ifndef _TCHAR_DEFINED
typedef WCHAR TCHAR, *PTCHAR;
typedef WCHAR TBYTE , *PTBYTE ;
#define _TCHAR_DEFINED
#endif /* !_TCHAR_DEFINED */

//....


Настройки(в релизе тоже самое):
Скрин (незнаю как по другому отобразить картинку  smile  )

Там в Release и Debug стоит "Use Unicode"...


Что же не так? Я так понимаю проблема в DLL? как сделать wchar_t UTF-16? 


--------------------
user posted image
PM WWW ICQ Skype   Вверх
Stepan_Lameroff
Дата 10.3.2007, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 164
Регистрация: 16.12.2006

Репутация: 9
Всего: 14



Подобные проблемы с wchar_t* (а еще были с wchar_t**  smile) у меня решились примерно так:

Код

[DllImport("yourDll.dll")]
public static extern void YourFunction(ref UInt16/*IntPtr*/ word);

string yourStr = "blahblahblah";
UInt16[] word = new UInt16[yourStr.Length];
TextReader txtReader = new StringReader(yourStr);
ReadInput(txtReader, word, 0, word.Length);
YourFunction(ref word[0]);

//или 
//
//IntPtr word = new IntPtr();
//UInt16[] wordBytes = new UInt16[yourStr.Length];
//word = Marshal.AllocCoTaskMem(Marshal.SizeOf(IntPtr.Size) * wordBytes.Length);
//Marshal.Copy(wordBytes, 0, word, wordBytes.Length);
//YourFunction(ref word);
//Marshal.FreeCoTaskMem(word);

//ну и ReadInput

public int ReadInput(TextReader sourceTextReader, UInt16[] target, int start, int count)
{
    if (target.Length == 0)
        return 0;

    char[] charArray = new char[target.Length];
    int bytesRead = sourceTextReader.Read(charArray, start, count);

    if (bytesRead == 0)
        return -1;

    for (int index = start; index < start + bytesRead; index++)
        target[index] = (UInt16)charArray[index];

    return bytesRead;
}


может и в Вашем случае заработает  smile 

PM MAIL   Вверх
FelikZ
Дата 10.3.2007, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Stepan_Lameroff, сработает smile я примерно так уже пробывал!

Что-то типа (пишу от руки, может и не откомпилица smile ):
Код

[DllImport("yourDll.dll")]
public static extern void YourFunction(uint[] word);

uint[] Convert(string toConvert)
{
     uint[] gg = new uint[toConvert.Lenght];
     for(int i=0;i<toConvert.Lenght;i++)
     {
           gg[i] = toConvert[i];
     }
     return gg;
}

static void main(string[] args)
{
     YourFunction(Convert("Все же оно работает!"));
}


Но я считаю что это не человечно, как то.... Есть другие варианты? (напр.  изменить как-то в проекте кодировку...)


--------------------
user posted image
PM WWW ICQ Skype   Вверх
FelikZ
Дата 11.3.2007, 11:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Свершилось! 

заменить:
Код

[DllImport("CoreLibraryd.dll")]

на:
Код

[DllImport("CoreLibraryd.dll", CharSet = CharSet.Unicode)]


И все тут )  smile 

ЗЫ. с утра лучше думается


--------------------
user posted image
PM WWW ICQ Skype   Вверх
FelikZ
Дата 12.3.2007, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Старый Маразматик
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 1.12.2006
Где: Vault 13

Репутация: нет
Всего: 5



Снова я :(

В длл:
Код

typedef struct tagFileTableObject
{
    DWORD cbSize;
    DWORD dwOffset;
    DWORD dwFileSize;
    TCHAR *strFileName;
    
}*LPFTOBJECT,FTOBJECT;


HRESULT CVirtualFolder_GetFileObject(void* class, TCHAR* strVirtualPath, LPFTOBJECT obj, bool asCopy)
{
    if(!_isvfopened)
    {DME(L"CVirtualFolder::GetFileObject: VFERR_VFNOTOPENED")return VFERR_VFNOTOPENED;}

    if(obj <= NULL)  //Здесь вылетает, тк указатель 'obj' равен нулю
    {DMW(L"CVirtualFolder::GetFileObject: Invalid Param")return VFERR_STANDARTERROR /* Эквивалент -1 */;}

         //...
}


прога:
Код


    unsafe public struct FileTableObject
    {
        public uint cbSize;
        public uint Offset;
        public uint FileSize;
        public char[] FileName;
    };

#if DEBUG
        [DllImport("CoreLibraryd.dll", CharSet = CharSet.Unicode)]
#else
        [DllImport("CoreLibrary.dll", CharSet = CharSet.Unicode)]
#endif //DEBUG
        private static extern unsafe VFErrorList CVirtualFolder_GetFileObject(void* pClass, char[] strVirtualPath, FileTableObject obj, bool asCopy);

//....

void* _selfClass;   //Указатель на класс CVirtualFolder

//...
//Получение указателя
//...

FileTableObject obj = new FileTableObject();

if( CVirtualFolder_GetFileObject(_selfClass, "datafile.file".ToCharArray(),  obj, false) < 0)
{
    Console.WriteLine("Вылет");
}


Что я делаю не так...  smile  Почему приходит указатель на нуль? 



--------------------
user posted image
PM WWW ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0832 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.