0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11

Обертка Native для DBX32 (использование в 1С)

19.06.2017, 06:40. Показов 3034. Ответов 18
Метки , c, с (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Прошу помощи. Есть библиотека DBX32.dll, которая предоставляет возможность работы с PCADом. 1С напрямую с такой работать не умеет, поэтому нужно сделать некоторую обертку. Опишу свои действия:
- скачал примеры внешних компонент от 1С, выбрал проект AddInNative. Без моего вмешательства компонента собирается и работает в 1С нормально.
- в поставке PCADа есть файлы: Dbx32.dll, Dbx32.h, Dbx32.lib, DbxUtils.cpp, DbxUtils.h. Заголовочные файлы я добавляю в проект, и подключаю их в основном файле:
C++
1
2
#include "Dbx32.h"
#include "DbxUtils.h"
- файл DbxUtils.cpp добавляю в проект. Полный путь до файла Dbx32.lib указываю в свойствах проекта Properties/Linker/Input/Additional Dependencies. Все файлы лежат в папке проекта.
- в файле Dbx32.h присутствуют следующее:
C++
1
2
extern DbxContext     tContext;       //  Global DBX Conversation Data
extern long           tStatus;        //  Global Return status variable
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//
//     Conversation and Context Structure - Returned by TOpenDesign
//
    
typedef struct                //           (pcb/sch/cmp)
{
    HCONV     hConv;          // Converstation handle
    long      appInst;        // Application instance
    long      version;        // DBX version
    long      language;       // Language type
    HWND      hWnd;           // Server's window handle.
    HANDLE    hMmf;           // Handle to memory mapped file.
    void*     pMmf;           // Pointer to mapped view of MMF.
 
} DbxContext;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
long 
DLLX TOpenDesign (long language,
                  long version, 
                  const char* pDesignName, 
                  DbxContext* pContext);
//
// TOpenDesign - (PCB/Sch) Establishes communication channel with 
// -----------             the specified ACCEL EDA application
//
//  Parameter     Type/Description
//  ---------     ----------------
//
//  language      long         Calling program language 
//                             (constant DBX_LANGUAGE)
//  version       long         DBX program version
//                             (constant DBX_VERSION)
//  pAppName      char*        Input application name ("pcb" or "sch")
//  pContext      DbxContext*  Output DBX converstation data
//
//
//  returns       long         DBX completion status
//
Чтобы вызвать TOpenDesign объявляю переменные:
C++
1
2
DbxContext *tContext = new DbxContext();
long tStatus;
вызываю метод
C++
1
tStatus = TOpenDesign(DBX_LANGUAGE, DBX_VERSION, "pcb", tContext);
При сборке пишет следующую ошибку:
Error C2040 'tContext': 'DbxContext *' differs in levels of indirection from 'DbxContext'

Подскажите, что делаю не так? Пробовал по-разному объявлять tConecxt, ничего не выходит.
Делаю в VS2015. С++ вижу всего неделю, уж сильно не пинайте.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
19.06.2017, 06:40
Ответы с готовыми решениями:

Использование .NET Native
Привет всем! Недавно узнал о .NET Native, который позволяет компилировать .NET-проекты (C# или VB) в нативный бинарный код так, что...

Обертка для PDO
Нашел на http://phpfaq.ru/pdo/pdo_wrapper простую обертку. Но не совсем понял, как она работает. <?php define('DB_HOST',...

Обертка для list
Есть следующая иерархия классов: class A {}; class B : public A {}; class C : public A {}; class D : public C {}; Я...

18
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
20.06.2017, 14:52
C++
1
extern DbxContext     tContext;
ключевое слово extern, говорит о тот
где то в файлах есть объявление
C++
1
DbxContext     tContext;
Вам остается ссылаться на эту переменную.
(чтобы отправить в функцию нужен амперсанд & tContext)
C++
1
2
3
//DbxContext *tContext = new DbxContext();
//long tStatus;
tStatus = TOpenDesign(DBX_LANGUAGE, DBX_VERSION, "pcb", & tContext);
Можно сделать повторное необязательное объявление, используя extern.

C++
1
2
3
4
extern DbxContext     tContext; //  переменная объявленная в другом месте
extern long tStatus;   //  переменная объявленная в другом месте
 
tStatus = TOpenDesign(DBX_LANGUAGE, DBX_VERSION, "pcb", & tContext);[
1
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
23.06.2017, 10:47  [ТС]
Спасибо большое. При повторном объявлении с использованием extern сыпались ошибки.
А вот объявления
C++
1
DbxContext     tContext;
я вовсе не нашел. Добавил в основной файл .cpp, и через амперсанд заработало.

Дальше сложнее, но пока движется.

Добавлено через 3 часа 22 минуты
Еще хотел бы спросить.
Пытаюсь вернуть значение из компоненты в 1С.
Есть такая функция как
C++
1
2
bool CAddInNative::CallAsFunc(const long lMethodNum,
                tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
Описание: Выполняется метод с порядковым номером lMethodNum. Если метод возвращает false,
возникает ошибка времени выполнения и выполнение модуля "1С:Предприятие 8" прекращается.
Память для массива параметров выделяется "1С:Предприятие 8". Если возвращаемое значение имеет
тип строка или двоичные данные, компонента выделяет память функцией AllocMemory менеджера памяти,
записывает туда данные и сохраняет этот адрес в соответствующем поле структуры.
"1С:Предприятие 8" освободит эту память вызовом FreeMemory.

Есть у неё параметр:
C++
1
2
pvarRetValue
Тип: tVariant*. Указатель на структуру tVariant, содержащую возвращаемое значение.
в него я пытаюсь вернуть хоть что-то. Но никак не выходит. Вроде как есть указатель, в который можно что-то положить, но не даёт соответствие типов.
Есть такая штука как
C++
1
#define TV_VT(X)          ((X)->vt)
даже не знаю как называется. Она, как я вычитал, может установить тип переменной tVariant и установить значение.
Пробовал вот так:
C++
1
2
TV_VT(pvarRetValue) = VTYPE_INT;
TV_VT(pvarRetValue) = tStatus;//тип long
но в 1С ничего не возвращается.

В примерах увидел, что используется AllocMemory. С этим методом не до конца разобрался.
В примере используют так:
C++
1
 m_iMemory->AllocMemory((void**)&pvarRetValue->pstrVal, paParams->strLen);
Подскажите, как мне поместить что-то в "ответный" параметр?
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
23.06.2017, 11:57
Цитата Сообщение от temmy70 Посмотреть сообщение
- файл DbxUtils.cpp добавляю в проект.
А зачем DbxUtils.cpp добавлять в проект?
Если он используется для сборки DBX32.dll, то добавлять в проект его не нужно.
Вообще, в документации к библиотеке должно же быть указано, какие файлы включить
в проект. Примеры какие-то должны быть.

Цитата Сообщение от temmy70 Посмотреть сообщение
А вот объявления

DbxContext tContext;
Не, это не то.Так вы создали локальную переменную.

Добавлено через 35 секунд
Цитата Сообщение от temmy70 Посмотреть сообщение
При повторном объявлении с использованием extern сыпались ошибки.
Пишите ошибки на форум.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
26.06.2017, 05:44  [ТС]
Если в основном файле AddInNative.cpp пишу
C++
1
2
extern DbxContext tContext;
extern long tStatus;
то пишет ошибку:

Error LNK2001 unresolved external symbol "struct DbxContext tContext" (?tContext@@3UDbxContext@@A) AddInNative
Error LNK2001 unresolved external symbol "long tStatus" (?tStatus@@3JA) AddInNative

Про DbxUtils в описании сказано, что необходимо для работы с единицами измерений и прочее. Сильно не вдавался, но включил на всякий случай.
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
27.06.2017, 05:23
Цитата Сообщение от temmy70 Посмотреть сообщение
Error LNK2001 unresolved external symbol "struct DbxContext tContext" (?tContext@@3UDbxContext@@A) AddInNative
Error LNK2001 unresolved external symbol "long tStatus" (?tStatus@@3JA) AddInNative
temmy70,
Мне это не понятно.
Тоже попытался обращаться к DBX32.dll. Через extern получаю аналогичную ошибку.
Без extern :
C++
1
2
3
4
5
6
    DbxContext tContext;
    long    tStatus;
 
    tStatus = TOpenDesign(DBX_LANGUAGE, DBX_VERSION, "pcb", &tContext);
    if (tStatus != DBX_OK)
        std::cout << "Error: " << tStatus << (tStatus == DBX_CONNECTION_ERROR ? " CONNECTION ERROR." : " .") << std::endl;
Если P-CAD не запущен в консоли CONNECTION ERROR.Запущен -- то выводит сообщение
"DBX in progress".

Но DbxContext tContext; и long tStatus; это локальные переменные. Раз они укзаны в DBX32.h через extern,
значит в каком то файле участвовавшем в сборке длл объявлены внешние переменные tContext
и tStatus. Иначе библиотека не собралась бы.

Да и в документации об этом говорится :
For convenience, a global variable tContext is provided in DBX32.H and DBX32.BAS and
may be used directly by your user program to receive and maintain this information. The
global variable tContext is used throughout this manual and in the samples provided with
your P-CAD DBX installation
Открывал конечно DBX32.H, но там нет глобальной переменной tContext.
Миниатюры
Обертка Native для DBX32 (использование в 1С)   Обертка Native для DBX32 (использование в 1С)  
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
27.06.2017, 05:38  [ТС]
RuningMan,
Получается у меня так же сейчас работает, и вроде как это правильно. Переменные объявлены как
C++
1
2
DbxContext tContext;
long tStatus;
И при взаимодействии с PCADом из 1С сейчас отрабатывают TOpenDesign, TGetDesignInfo, TCloseDesign, вроде как всё корректно. Каждый из методов вызывается из 1С, по нажатию кнопок, но между нажатиями существует один и тот же экземпляр компоненты. То есть в нем (в экземпляре компоненты), всегда одна и та же переменная tContext.
Честно тяжело с С++, так как я первый раз с этим столкнулся.
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
27.06.2017, 05:41
Похоже на несоответствие заголовочных файлов библиотекам. Или документация устарела.

Добавлено через 3 минуты
Цитата Сообщение от temmy70 Посмотреть сообщение
То есть в нем (в экземпляре компоненты), всегда одна и та же переменная tContext.
Потому что она локальная, а где Та что в библиотеке и как её искать -- загадка.
PS Это всего лишь моё скромное мнение .
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
27.06.2017, 05:49  [ТС]
RuningMan, к сожалению, не совсем понимаю вас. Не хватает мне знаний по плюсам.
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
27.06.2017, 06:20
В заголовочных файлах, там есть класс который наследуется от CView,
у него есть поля DbxContext tContext , long tStatus
и коменнтарий к ним стоит // Global DBX Conversation Data
// Global Return status variable . Почему то ???

Но это же совсем не то.
Цитата Сообщение от temmy70 Посмотреть сообщение
к сожалению, не совсем понимаю вас. Не хватает мне знаний по плюсам
Да тут только понимать что есть локальные переменные, а что глобальные.
Вот где эти глобальные переменные ? .. Не нашёл.

Добавлено через 5 минут
Цитата Сообщение от RuningMan Посмотреть сообщение
В заголовочных файлах, там есть класс который наследуется от CView,
у него есть поля DbxContext tContext , long tStatus
и коменнтарий к ним стоит // Global DBX Conversation Data
// Global Return status variable .
Понял, это они. Но с MFC никогда прежде не возился.

Добавлено через 21 минуту
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// dbxsavw.h : interface of the CDbxsamp4View class
//
/////////////////////////////////////////////////////////////////////////////
 
#include "dbx32.h"
 
class CDbxsamp4View : public CView
{
public:
 
    CButton *pStartButton;
    CButton *pExitButton;
    
protected: // create from serialization only
    CDbxsamp4View();
    DECLARE_DYNCREATE(CDbxsamp4View)
 
// Operations
public:
 
..........
 
    DbxContext      tContext;       // Global DBX Conversation Data
    long            tStatus;        // Global Return status variable
};
Вот к этим переменным, полям класса вероятно и нужно обращаться.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
27.06.2017, 06:39  [ТС]
то есть в начале файла *.cpp так описываем, и они у нас становятся глобальными?
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
27.06.2017, 06:49
Цитата Сообщение от temmy70 Посмотреть сообщение
то есть в начале файла *.cpp так описываем, и они у нас становятся глобальными?
Не-не, код вверху это то что откопал в файлах.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
27.06.2017, 07:47  [ТС]
Цитата Сообщение от RuningMan Посмотреть сообщение
Не-не, код вверху это то что откопал в файлах.
ага, тоже нашел, я так понял это пример какой-то.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
27.06.2017, 12:31  [ТС]
Продолжая тему обертки.
Native не позволяет передавать объекты, только простые типы. Для общения с 1С сложными объектами, планирую использовать json.
В интернете есть много парсеров. Пробовал воспользоваться json.hpp. Но с этим файлом не компилируется проект.

например сюда ругается:
C++
1
2
3
4
5
6
7
8
// taken from ranges-v3
template<typename T>
struct static_const
{
    static constexpr T value{};
};
    template<typename T>
constexpr T static_const<T>::value;
Как исправить ошибки, или может другой есть удобный парсер?
Миниатюры
Обертка Native для DBX32 (использование в 1С)  
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
28.06.2017, 05:23
Цитата Сообщение от temmy70 Посмотреть сообщение
Native не позволяет передавать объекты, только простые типы. Для общения с 1С сложными объектами, планирую использовать json.
Извините если лезу куда не в своё дело.
Скопировано с habrahabr.ru
Кликните здесь для просмотра всего текста
Тип данных tVariant

При обмене данными между внешней компонентой и системой «1С: Предприятие» используется тип данных tVariant. Он описан в файле types.h, который можно найти на диске с ИТС:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct _tVariant 
{ 
    _ANONYMOUS_UNION union 
    { 
        int8_t         i8Val; 
        int16_t        shortVal; 
        int32_t        lVal; 
        int            intVal; 
        unsigned int   uintVal; 
        int64_t        llVal; 
        uint8_t        ui8Val; 
        uint16_t       ushortVal; 
        uint32_t       ulVal; 
        uint64_t       ullVal; 
        int32_t        errCode; 
        long           hRes; 
        float          fltVal; 
        double         dblVal; 
        bool           bVal; 
        char           chVal; 
        wchar_t        wchVal; 
        DATE           date; 
        IID            IDVal; 
        struct _tVariant *pvarVal; 
        struct tm      tmVal; 
        _ANONYMOUS_STRUCT struct 
        { 
            void*  pInterfaceVal; 
            IID        InterfaceID; 
        } __VARIANT_NAME_2/*iface*/; 
        _ANONYMOUS_STRUCT struct 
        { 
            char*        pstrVal; 
            uint32_t     strLen; //count of bytes 
        } __VARIANT_NAME_3/*str*/; 
        _ANONYMOUS_STRUCT struct 
        { 
            WCHAR_T*    pwstrVal; 
            uint32_t    wstrLen; //count of symbol 
        } __VARIANT_NAME_4/*wstr*/; 
    } __VARIANT_NAME_1; 
    uint32_t      cbElements;    //Dimension for an one-dimensional array in pvarVal 
    TYPEVAR       vt; 
};
Тип tVariant представляет из себя структру, которая включает себя:
смесь (union), предназначенную непосредственно для хранения данных
идентификатор типа данных

В общем случае работа с переменными типа tVariant происходит по следующему алгоритму:
Определение типа данных, которые в данный момент хранятся в переменной
Обращение к соответствующему полю смеси, для непосредственного доступа к данным

Использование типа tVariant значительно упрощает взаимодействие системы «1С: Предприятие» и внешней компоненты
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
29.06.2017, 05:19  [ТС]
RuningMan, тоже читал эту статью. Насколько я разобрался, такую структуру ждет 1С от внешней компоненты. Платформа 1С получает эту структуру, в зависимости от типа забирает соответствующее значение и пытается его привести к своему внутреннему типу. Это я так понял, но могу ошибаться.
В vt я должен указать какого типа будут данные, и потом в соответствующее свойство записать данные.
Например:
C++
1
2
pvarRetValue->vt = VTYPE_I4;
pvarRetValue->lVal = tStatus;
C++
1
2
3
pvarRetValue->vt = VTYPE_PWSTR;
pvarRetValue->pwstrVal = wsOutStr;
pvarRetValue->strLen = newsize - 1;
В описании типа указано
C++
1
struct _tVariant *pvarVal;
что, как я думаю, подошло бы для передачи произвольных сложных объектов, но на ИТС указано, что этот тип не поддерживается.
И в комментариях к статье на хабре тоже писали, что передача массив все еще недоступна, только простые типы. Поэтому приходится придумывать.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
06.07.2017, 06:13  [ТС]
Добрый день, RunningMan, продолжаю пилить свою компоненту для PCAD. Я так понял, что у вас был подобный опыт взаимодействия с PCAD, может быть подскажете один момент.

Реализовал вставку компонента в pcb, чтение элементов из pcb. Работает всё хорошо.
Взялся за вставку в sch, и получил проблемку. При первой попытке вставляю компонент, нормально. При повторном обращении к sch у меня крашится 1С. Есть ли там какие-либо хитрые отличия работы с sch от работы с pcb.
При этом я получаю информацию о sch, получаю перечень слоёв(листов). Но вот только после вставки компонента происходит вылет.
0
 Аватар для RunningMan
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
06.07.2017, 11:05
Здравствуйте.
Цитата Сообщение от temmy70 Посмотреть сообщение
что у вас был подобный опыт взаимодействия с PCAD,
Всего лишь есть доступ к машине на которой PCAD установлен. Никогда PCAD не пользовался.
1С в наличии нет, поэтому смоделировать полностью вашу ситуацию к сожалению не получится.
0
0 / 0 / 0
Регистрация: 19.06.2017
Сообщений: 11
06.07.2017, 11:25  [ТС]
RunningMan, понял.
Уже разобрался, как обычно, стоит только написать вопрос.

Добавлено через 16 секунд
RunningMan, понял.
Уже разобрался, как обычно, стоит только написать вопрос.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.07.2017, 11:25
Помогаю со студенческими работами здесь

Обертка для rsync
написал вот такую обертку для rsync в личных целях #! /usr/bin/python3 import subprocess import datetime import sys import re ...

C++ обертка для OpenGL?
Здраствуйте. Почему для OpenGL до сих пор нету хорошей обертки для языка C++? Который одновременно являлся низкоуровненным как OpenGL и...

Обертка для изображений
Подскажите, пожалуйста, как можно сделать подобную обертку для изображений (изображения будут подставляться разные), чтобы так же обрезало...

C++ обертка для dll C
Как написать C++ обертку для динамической библиотеки C?

Дополнительная обертка для слайдера
Столкнулся с такой ситуацией: делал слайдер точно по примеру, использовал owl carousel, но у меня карусель не отображалась, в итоге...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

Новые блоги и статьи
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20%
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru