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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование NET-сборки в COM коде, trubleshooting 
V
    Опции темы
Linus
Дата 18.10.2007, 07:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



Вот интересная штука получается. Написал dll библиотеку на C#, в которой есть такой код:
Код

//Program.cs:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MakingBases3
{
    [ComVisible(true)]
    public static class Program
    {
        [STAThread]
        [ComVisible(true)]
        public static void StartBank()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Потом сделал tlh-файл:
Код

C:\Program Files\Microsoft Visual Studio 8\VC>tlbexp С:\1\MakingBases3.dll /out: C:\1\MakingBases3.tlh

После чего создал на С++ Win32 Comsole Application:
Код

#include "stdafx.h"
#import "c:\1\MakingBases3.tlh"

using namespace MakingBases3;

int _tmain()
{
    //MakingBases3::Program; - и "MakingBases3", и "Program" в этом месте мне подсказал intellisence
    return 0;
}

Код скомпилировался. И пространство имён MakingBases3, и класс Program С++ увидела. А вот метода StartBank() в классе Program никак не хочет видеть. В чём я виноват?
P.S. Класс Program интеллисенс увидел как структуру.
PM MAIL ICQ   Вверх
tol05
Дата 18.10.2007, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



если не ошибаюсь, то ты должен создать интерфейс, потом - класс, его реализующий. И на клиенте работать не с твоим классом, а с интерфейсом.

Будет что-то типа
Код

namespace MakingBases3
{

public interface IStart
{
   void StartBank();
}

    [ComVisible(true)]
    public class Program : IStart
    {
        [STAThread]
        [ComVisible(true)]
        public void StartBank()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Код

#include "stdafx.h"
#import "c:\1\MakingBases3.tlh"
using namespace MakingBases3;
int _tmain()
{
    //MakingBases3::IStart istart;
    //istart->StartBank();
    return 0;
}




Это сообщение отредактировал(а) tol05 - 18.10.2007, 08:14


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Linus
Дата 18.10.2007, 08:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



tol05, большое спасибо, сейчас попробую.
И ещё: только что скачал небольшую презентацию, так там написано:
Цитата

Использование типов .NET в COM
* Обратная совместимость + взаимодействие
* Необходимо создать библиотеку типов COM
   TLBEXP MyLib.dll
* Затем надо сослаться на TLB:
   #import в Visual C++ 6.0
   Project/Reference в Visual Basic 6.0
*Наконец, надо проинсталлировать и зарегистрировать сборку:
   RegAsm MyLib.dll            (beta 1)
   GACUTIL /ir:Mylib.dll       (beta 2)

Информация к размышлению
* Не все типы .NET доступны в COM:
   Только public типы и переменные 
   Статически члены недоступны
* Создаваемые классы должны иметь конструктор по умолчанию
* Функциональность должна быть доступна через интерфейсы
* GUID автоматически генерируются при экспорте
   На основе имен сборки и типа
   На основе полного определения интерфейса
* Сборка должна быть доступна во время исполнения
* Сборка должна находиться в каталоге приложения или быть доступна еще каким-то образом

Значит нельзя использовать статические переменные/классы. Сейчас буду пробовать, о результатах отпишусь.
PM MAIL ICQ   Вверх
Linus
Дата 18.10.2007, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



tol05, спп ругается на MakingBases3::IStart istart (над этим интерфейсом я тоже повесил атрибут СomVisible(true)):
Цитата
error C2259: 'MakingBases3::Istart' : cannot instantiate abstract class    c:\Vsproj\C++\consoleproba\consoleproba\consoleproba.cpp

В пространстве имён MakingBases3 в intellisence светятся:
Цитата
__MakingBases3
_Program
_ProgramPrt
Program
Istart
IstartPtr

Чем отличаются друг от друга _Program от Program для меня загадка...

Это сообщение отредактировал(а) Linus - 18.10.2007, 09:12
PM MAIL ICQ   Вверх
Linus
Дата 18.10.2007, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



Уже повесил на interface Istart атроибут [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)], и с бубном танцевал, и до сих пор не могу в C++ создать экземпляр класса Program:
Цитата
'MakingBases3::Program' : no appropriate default constructor available

Чего ж ему конструктор по умолчанию не угодил? Так... Исследования продолжаются....   smile 

Это сообщение отредактировал(а) Linus - 18.10.2007, 09:42
PM MAIL ICQ   Вверх
Tauler
Дата 18.10.2007, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



сейчас имею отношения (или со мной имеет отношения smile ) аналогичная проблема. Предлагаю дружить домами. Моё асько - 309-421-824.
PM MAIL   Вверх
tol05
Дата 18.10.2007, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Цитата(Linus @  18.10.2007,  08:29 Найти цитируемый пост)
Значит нельзя использовать статические переменные/классы

правильно, я и убрал static из своего кода.


Цитата(Linus @  18.10.2007,  09:39 Найти цитируемый пост)
Чего ж ему конструктор по умолчанию не угодил? 

пропиши в классе конструктор явно
Код

public class Program : IStart
    {
        public StartBank() {}
         ...
    }


поищи книгу "C#2005 для профессионалов". Там неплохие примеры есть.
А у меня счас ее нет, а сам - не помню smile Извини


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Linus
Дата 18.10.2007, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



Цитата

правильно, я и убрал static из своего кода

аха, я потом увидел, как свой пост опубликовал smile
Цитата

пропиши в классе конструктор явно

Прописывал (конструктор без параметров). Бестолку, всё равно ругалось (no appropriate default constructor available)...
Цитата

поищи книгу "C#2005 для профессионалов". Там неплохие примеры есть.

Дык на полке лежит) Уже нашёл, сейчас читаю... (я по Троелсену пытался разбирать, и забыл за эту книжку)
PM MAIL ICQ   Вверх
Linus
Дата 18.10.2007, 13:19 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



Ура, получилось! К сожалению мне сейчас убегать надо, как домой приду напишу сюда пример.
PM MAIL ICQ   Вверх
Linus
Дата 18.10.2007, 16:52 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

Репутация: 1
Всего: 4



Итак, чтобы народ впредь так не мучился в поисках вразумительных примеров чтобы понять суть дела, кратко разжёвываю (самый необходимый минимум):
Сначала пишем класс на .NET (назовём сборку NetClass), который потом будем использовать в комовском коде:
Код

using System;
using System.Runtime.InteropServices; //Подключили для аттрибутов ComVisible и ProgId

namespace Vingrad
{
    [ComVisible(true)]  //Этот интерфейс будет виден комовскому коду.
    public interface IVingrad
    {
        void PrintMessage(string user); //Метод, выводящий строку на экран
    }

    [ComVisible(true)] //Этот класс будет виден комовскому коду.
    [ProgId("VingradNetCom")] //Для спецификации имени, используемого при конфигурации объекта в реестре
    public class NetClass : IVingrad //Наш класс, реализующий интерфейс IVingrad
    {
        public void PrintMessage(string user)
        {
            Console.WriteLine("Congratulations, {0} you called me from unmanaged C++!", user);
        }
    }
}

Скомпилировали в dll. Прежде, чем компонент .NET может быть использован как объект COM, его необходимо сконфигурировать в реестре и создать CCW (COM Callable Wrapper) – вызываемую оболочку, через которую будут взаимодействовать клиент COM c объектом NET. В Visual Studio 2005 Command Prompt:
Цитата(Visual Studio 2005 Command Prompt)
C:\Program Files\Microsoft Visual Studio 8\VC>regasm C:\Vsproj\Vingrad\NetClass\
NetClass\bin\Debug\NetClass.dll /tlb

Microsoft ® .NET Framework Assembly Registration Utility 2.0.50727.42
Copyright © Microsoft Corporation 1998-2004.  All rights reserved.

Types registered successfully
Assembly exported to 'C:\Vsproj\Vingrad\NetClass\NetClass\bin\Debug\NetClass.tlb
', and the type library was registered successfully

Так… Сборку зарегистрировали, при том в папке bin\Debug рядом с NetClass.dll появился NetClass.tlb (это наш COM Callable Wrapper).
Теперь пишем клиента (создаём на С++ Win32 Console Application):
Код

#include "stdafx.h"
#include "conio.h"
#include "iostream"
//Подключим NetClass.tlb (путь к нему поставьте свой)
#import "C:\Vsproj\UsingNetFromComProjects\NetClass\NetClass\bin\Debug\NetClass.tlb"

using namespace std;

int _tmain()
{
    HRESULT hr;
    hr = CoInitialize(NULL); //Инициализируем COM (создаём и входим в STA потока)

    try
    {
        NetClass::IVingradPtr spVingrad; //Создаём указатель
        hr = spVingrad.CreateInstance("VingradNetCom");  //Создаём COM-объект
        cout << spVingrad->PrintMessage("Linus"); //Вызываем метод
    }
    catch(_com_error& e)
    {
        cout << "Error " << e.ErrorMessage() << endl; //Произошла ошибка.
    }

    getch();
    CoUninitialize(); //Закрываем и выгружаем библиотеки dll COM
    return 0;
}

Так как мы не регистрировали сборку NetClass.dll в GAC, то нужно скопировать её рядом с исполняемым файлом COM- клиента, чтобы он её увидел. Запускаем:
Цитата(cmd.exe)

Congratulations, Linus you called me from unmanaged C++!
0

P.S. Спасибо участникам форума, Кристиану Нейгелу, Биллу Ивьену и другим авторам за активное содействие в написании поста)

Это сообщение отредактировал(а) Linus - 18.10.2007, 17:15

Присоединённый файл ( Кол-во скачиваний: 10 )
Присоединённый файл  UsingNetFromComProjects.zip 36,19 Kb
PM MAIL ICQ   Вверх
Experimenter
Дата 30.10.2007, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 8
Всего: 17



Все же непонятно - могу ли я в дотнете создать comvisible сборку dll и из дотнетовской же программы юзать ее при помощи dllimport? Ничего не получилось у меня. Почему спрашиваю - ни на чем другом писать не умею, а протестировать надо как-то.


--------------------
public Zlo FromTwoEvilsChooseSmaller(Zlo zlo1, Zlo zlo2){
    if(zlo1 < zlo2) return zlo1;
    else if(zlo1 > zlo2) return zlo2;
    else throw new Exception("Kill yourself by the wall"); }
PM WWW ICQ   Вверх
tol05
Дата 30.10.2007, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



нет не можешь. На самом деле никакой COM сборки .Net не создает, а создает только врапперы для ее COM-visibility (я имею в виду CCW и RCW).
когда ты пытаешься присоединить эту сборку в студии, CLR читает .Net манифест сборки и видит, что это - .Net сборка и подключать ее нужно через Add Reference.
Когда мне нужно было тестировать свою сборку - я тестировал ее на реальном COM-сервере. 

Единственное, что могу посоветовать - это разбить сборку на части, где одна будет выступать в роли COM-visible объекта, другие будут обычными .Net библиотеками и содержать логику работы. Тогда ты сможешь тестировать работу в обычном режиме Add Reference, а при работе с сервером - он будет тянуть твою COM-visible сборку, а она - остальные .Net-библиотеки.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Experimenter
Дата 14.5.2008, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 8
Всего: 17



Пришлось поднять тему из небытия.
Проясните один момент, плиз! Видимо если .NET Framework не установлен на машине, то все, о чем здесь говорилось, не сработает? Ответ и так почти ясен (нет), но не хватает твердой уверенности.


--------------------
public Zlo FromTwoEvilsChooseSmaller(Zlo zlo1, Zlo zlo2){
    if(zlo1 < zlo2) return zlo1;
    else if(zlo1 > zlo2) return zlo2;
    else throw new Exception("Kill yourself by the wall"); }
PM WWW ICQ   Вверх
alexsid1982
Дата 15.5.2008, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Для твердой уверенности:

Нет не сработает.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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