ksTransferInterface не возвращает объект

Автор Неоненко, 19.02.15, 09:23:18

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Неоненко

Добрый день!
Пожалуйста, подскажите, в чем может быть проблема.
Не удается преобразовать объект API7 в API5 с помощью функции ksTransferInterface, функция возвращает nil

var
  part7: IPart7;
  part5: IPart;
begin
  part5 := IUnknown( ksTransferInterface(PIUnknown(part7), ksAPI3DCom, o3d_part) ) As IPart;

Интерфейс IPart7 я предварительно получаю в процессе обхода дерева модели.

При каких условиях работает ksTransferInterface - только в прикладной библиотеке, вызванной из КОМПАС или должна работать и в случае вызова из внешнего приложения, которое создает экземпляр приложения КОМПАС через COM?

19.02.15, 09:41:17 #1 Последнее редактирование: 19.02.15, 09:57:55 от Sabahs
Преобразуйте документ из API7 в API5, а затем у него получите IPart.
pDocument3D:=IUnknown(ksTransferInterface(LtDefine.PIUnknown(Doc3D),ksAPI3DCom,0)) as IDocument3D;
if pDocument3D<>nil then pPart:=IPart(pDocument3D.GetPart(pTop_Part));

Неоненко

Благодарю за ответ!

преобразовать документ тоже не удается, функция возвращает nil

doc7: IKompasDocument3D;
doc5: IDocument3D;

doc5 := IUnknown( ksTransferInterface(LtDefine.PIUnknown(doc7), ksAPI3DCom, 0) ) as IDocument3D;

есть сомнение, что ksTransferInterface вообще работает при вызове из внешнего приложения.

и, насколько я понимаю, мне преобразование документа с последующим получением у него парта не подходит. у парта api5 невозможно (или мне не удалось найти?) получить парты, образующие массив (то что возвращает IPart7.PartsEx). Если бы в api5 можно было получить парты массива и свойства, то можно было бы пользоваться только им, без api7.


Неоненко

Если сократить и упростить, то получится примерно следующее

var
  kompas7: IApplication;
  docs7: IDocuments;
  doc7: IKompasDocument3D;
  top_part, part7 : IPart7;
  partsEx: OleVariant;
begin
  kompas7 := CreateComObject(CLASS_KompasInvisible7) as IApplication;
  docs7 := kompas7.Documents;
  doc7 := docs7.Open(FName, false, true) as IKompasDocument3D;
  top_part := doc7.TopPart;

  partsEx := top_part.PartsEx[ksAllParts];
  If VarType(partsEx)=(varArray or varDispatch) then begin
    c := VarArrayHighBound(partsEx, 1) - VarArrayLowBound(partsEx, 1);
    for i := 0 to c do begin     
      part7 := IDispatch(partsEx) as iPart7;
      if ( part7 <> nil ) then
        part5 := IUnknown( ksTransferInterface(PIUnknown(part7), ksAPI3DCom, o3d_part) ) As IPart;
      under_part := nil;
    end;
  end;

Как вариант делаете так http://forum.ascon.ru/index.php/topic,27429.msg204826.html#msg204826
У KompasObject есть метод ksTransferInterface, который должен работать, но преобразовываете документ, а затем у него получите IPart, как писал выше.

Неоненко

т.е. советуете начинать работу сразу с api5?
как тогда получать парты из массивов?


Неоненко

в любом случае - не помогло.

  kompas5 := KompasObject(CreateOleObject('Kompas.Application.5'));
  kompas7:=GetActiveOleObject('Kompas.Application.7') as IApplication;
далее как раньше
  docs7 := kompas7.Documents;
  doc7 := docs7.Open(FName, false, true) as IKompasDocument3D;

  doc5 := IUnknown( ksTransferInterface(LtDefine.PIUnknown(doc7), ksAPI3DCom, 0) ) as IDocument3D;  //возвращает nil

  top_part := doc7.TopPart;
  partsEx := top_part.PartsEx[ksAllParts];
  If VarType(partsEx)=(varArray or varDispatch) then begin
    c := VarArrayHighBound(partsEx, 1) - VarArrayLowBound(partsEx, 1);
    for i := 0 to c do begin     
      part7 := IDispatch(partsEx) as iPart7;
      if ( part7 <> nil ) then
        part5 := IUnknown( ksTransferInterface(PIUnknown(part7), ksAPI3DCom, o3d_part) ) As IPart; //возвращает nil
      under_part := nil;
    end;
  end;

То есть так не хочет?
kompas5.ksPumpWaitingMessages;
doc5 := IUnknown( kompas5.ksTransferInterface(LtDefine.PIUnknown(doc7), ksAPI3DCom, 0) ) as IDocument3D;

Неоненко

получается следующая картина

  hr: HResult;
  part5u: IUnknown;
  part5: IPart;

  //возвращает ссылку на объект, но IPart у него получить нельзя
  part5u := kompas5.TransferInterface(IUnknown(part7), ksAPI3DCom, o3d_part);
  if part5u <> nil then begin
    hr := part5u.QueryInterface(IPart, part5);
    if Succeeded(hr) then begin end; //not Succeeded
  end;

с документом аналогичная картина, привожу пример с партом, т.к. меня именно он интересует, а не документ.

Парт возвращать не должен, а документ должен.

Неоненко

почему парт не должен, а документ должен? есть принципиальное различие? сейчас еще раз попробую документ, но, вероятно, эффект будет аналогичным.
в примерах sdk есть преобразование парта, т.е, чисто теоретически, работать оно тоже должно

апд
с документом абсолютно то же самое - возвращается ссылка на некий объект, получит из которого IDocument3D не удается

Вместо этого part5u := kompas5.TransferInterface(IUnknown(doc7), ksAPI3DCom, 0);
попробуйте так
doc5 := IUnknown( kompas5.ksTransferInterface(PIUnknown(doc7), ksAPI3DCom, 0) ) as IDocument3D;
или так
part5u := ksPart(kompas5.TransferInterface(PIUnknown(part7), ksAPI5Auto, o3d_part));



Неоненко

насколько я понимаю, это аналогичные действия, только в моем случае проще обработать ошибку.
если делать так
doc5 := IUnknown( kompas5.ksTransferInterface(PIUnknown(doc7), ksAPI3DCom, 0) ) as IDocument3D;
получаем вот такое сообщение, виновник - AS

Раз ksTransferInterface нормально в exe не работает, то просто в API5 получить указать на активный документ и у него получить Part.
PS. В DLL ksTransferInterface работает нормально.

Неоненко


Цитата: Неоненко от 19.02.15, 11:59:14
это dll
Тогда зачем Вам следующие строки?
kompas5 := KompasObject(CreateOleObject('Kompas.Application.5'));
kompas7 := CreateComObject(CLASS_KompasInvisible7) as IApplication;

Неоненко

Думаю, что справедливо будет заметить, что dll разные бывают. Вы, вероятно, имеете в виду dll-библиотеку, вызванную из КОМПАС, моя же dll запускается не из-под КОМПАСА, а из внешнего приложения, которое и создает экземпляр приложения КОМПАС через COM.

Решение проблемы:
Опытным путем удалось установить, что TransferInterface работает только из-под КОМПАСА! Из внешнего приложения с созданием экземпляра КОМПАСА функция не работает, во всяком случае я не смогла заставить ее работать.

Slaviation

ЦитироватьОпытным путем удалось установить, что TransferInterface работает только из-под КОМПАСА! Из внешнего приложения с созданием экземпляра КОМПАСА функция не работает, во всяком случае я не смогла заставить ее работать.

Предлагаю так же получить интерфейс KompasObject (интерфейс API5 КОМПАС) и использовать KompasObject::ТransferInterface.
Тест на Python в прицепе. Работает не из под КОМПАС. Запускать на активной детали или сборке.