Создание dll в delphi 7 для 1с

Обновлено: 06.07.2024

Есть dll без исходников, для нее есть интерфейс на delphi. Стоит задача подружить эту библиотеку с 1С. На сколько понял с прочитанного в интернете, на основе интерфейса можно сделать dll по COM технологии.

Как правильно написать такую dll, чтобы функция из примера была доступна из 1С?

8,611 2 2 золотых знака 17 17 серебряных знаков 34 34 бронзовых знака вопрос только зачем этот костыль нужен. а так хоть две промежуточных длл пишите. Да, это враппер, причём достаточно простой. Но вопрос у вас общий, поэтому ответ - да, это реализуемо :) > вопрос только зачем этот костыль нужен. а так хоть две промежуточных длл пишите. – teran Есть бизнес система с которой можно взаимодействовать через эту dll. Напрямую с 1С она не работает, поэтому приходится извращаться. Может есть какая-нибудь статья или пример кода для похожего решения? Или хотя бы примерная структура для такой dll?

Ваша библиотека будет связующим звеном между 1C и сторонней библиотекой без исходного кода:

То, что вы описали - попытка реализовать связь:

Осталось реализовать связь между 1C и вашей библиотекой.

Чтобы начать разработку библиотеки по технологии COM в Delphi нужно выбрать: File -> New -> Other и там найти ActiveX Library, новый проект будет выглядить приблизительно так:

НовыйПроект

Далее к проекту добавить COM-сервер: File -> New -> Other и найти COM Object, выглядеть в новых версиях Delphi будет как-то так:

НоваяDelphi

В старых версиях Delphi так:

СтараяDelphi

В полях ClassName (CoClassName) нужно ввести английское название, по которому 1C и будет загружать вашу библиотеку после регистрации в системе, например: MaximLibrary1C

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

Конечно, имя проекта лучше задать более вменяемое, а не Project1. На машине с Delphi зарегистрировать можно из среды в меню "Run". Из самой 1C вашу библиотеку после регистрации в системе можно будет загружать как-то так:

Насколько мне известно, многие 1С-ники хотели бы изучить написание внешних компонент, чтобы поднять свое магическое искусство 1С на качественно иную ступень.

Что этому может помешать? Во-первых, известный синдром компонентофобии (который исторически берет свое начало от криво написанных внешних компонент). Во-вторых –синдром клинически запутанного кода. OLE-программирование – это не самая простая штука, и, как говорится, «не всякая птица долетит до середины Днепра» (особенно, если эта «птица» – программист 1С).

Я предлагаю вашему вниманию шаблон внешней компоненты, который, как я надеюсь, достаточно прост для понимания (я постарался его значительно упростить по сравнению с типовым примером из «Технологии создания внешних компонент») и стабилен (везде, где это возможно, я использую обработку исключительных ситуаций).

Сборка проекта

Для компиляции примера потребуется среда разработки Delphi 6 или 7.

Файл проекта - TestVK.dpr.
Откройте этот файл (например, двойным щелчком мыши из Проводника).
Нажмите сочетание клавиш Ctrl-F9 (или пункт меню Project-Compile). Если все прошло нормально, в этой же папке образуется готовая внешняя компонента TestVK.dll (для проверки, а все ли хорошо, ее можно удалить, и получить готовую TestVK.dll еще раз).

Проверка работоспособности DLL

В комплект примера входит тестовая конфигурация 1С:Предприятие 7.7.

Переименование DLL

Первое, что я делаю при создании новой внешней компоненты – переименовываю уже существующий образец.

Переименуйте TestVK.dpr так, как вы хотите (например, MyVK.dpr).

Произведите замену всех вхождений подстроки TestVK в файлах проекта на нужное вам имя внешней компоненты.

Подсказка: чтобы открыть другие модули проекта, используйте пункт меню View-Units…

Программный код 1С, разумеется, также нужно не забыть изменить так, чтобы заменить все подстроки «TestVK».

Важно: замените значение CLSID внешней компоненты, чтобы новая DLL, с точки зрения Windows, стала действительно новой.

Чтобы сгенерировать новый CLSID, нажмите сочетание клавиш Ctrl-Shift-G.

Попробуйте скомпилировать новый проект – 1С должна «увидеть» вашу новую внешнюю компоненту, которая создана на основе другой ВК, но содержит полный набор ее свойств и методов.

Что такое свойства и методы?

Новички могут задаться вопросом, а что такое свойства и что такое методы?
В коде 1С свойства выглядят как, своего рода, «переменные», объекта, доступные через точку, например

Здесь объект – имеет имя vk (посмотрите, как он объявляется и инициализируется в глобальном модуле 1С).. Этот объект поддерживает свойства и методы.

В этом коде я установил свойству "Заголовок" текстовое значение (посмотрите, как будет работать пример, если установить этому свойству другое значение заголовка, например, «Здесь был romix», или не устанавливать его вовсе).

Метод объекта – это, своего рода, «функция» объекта, доступная «через точку».

Изменение списка свойств и методов ВК

В модуле AddinObj.pas за количество свойств отвечают участки кода, которые я пометил (*2*), (*5*), (*6*), (*8*), (*11*) а за количество методов - (*3*), (*7*), (*9*), (*10*), (*12*).

Я завел в шаблон по 5 свойств и методов, но что нужно сделать, чтобы их стало 6, например, в приведенном ниже фрагменте кода, - я надеюсь, понятно без объяснений.

Вы можете завести свойства и методы «с запасом» - лишние заготовки не повредят (их можно будет оставить пустыми).

Программирование функциональности свойств

Откройте (через меню View – Units…) модуль vk_object.pas

Для свойств вы увидите примерно такой код, продублированный, с небольшими отличиями, несколько раз: Это самая важная часть наших действий, которую важно постараться понять.

Что я здесь делаю?

Программирование функциональности методов

Для методов код похожий:

Этот абзац можно воспроизвести несколько раз (что и сделано в примере), заменив meth1 на meth2, meth3 и т.д.

Приведенные ниже строчки устанавливают русское и английское имя метода.

Попробуйте изменить то или другое, перекомпилировать проект и посмотреть, что получится.

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

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

Возвращаемое значение функции

Чтобы вернуть значение из функции, надо установить переменную g_Value, например:

Отладочная печать

Вы можете в качестве теста вписать в функциональность метода что-то свое, например,

Этот вызов покажет стандартное окно предупреждения с кнопкой ОК. Или вот так:

Во втором случае, если Delphi будет ругаться при компиляции, добавьте Dialogs в раздел uses модуля.

Получение параметров функции

В своей функции я завел две переменные для хранения параметров:

Сейчас мы их заполним значениями, полученными из 1С.

Параметры нумеруются, начиная с 0 (давняя традиция программистов на языке С).

Чем отличаются AsString и AsInteger, надеюсь, понятно.

Этот код можно было бы написать и так:

Отладочная печать параметров

При отладке полученные из 1С значения полезно выводить на экран. Но как это сделать?
Я обычно использую следующий прием:

Чтобы показать строковые переменные, я пишу так:

А числовые значения и значение типа "дата-время" я отображаю примерно так:

Функциональность методов

Получив все значения из 1С, можно приступать к собственно написанию полезного кода.

Узнавать, как работают те или иные функции API, можно в поисковых машинах или в сборниках Delphi FAQ, которые в изобилии выложены в сети Интернет.

Использование DLL (динамически подключаемая библиотека) широко распространено в программировании Windows. DLL на самом деле часть кода исполняемого файла с расширением DLL. Любая программа может вызывать DLL.

Преимущество DLL заключается в следующем:

  • Повторное использование кода.
  • Совместное использование кода приложениями.
  • Разделение кода.
  • Улучшение потребления ресурсов в Windows.

Создание DLL

В меню File выберите пункт New -> Other . В диалоговом окне на вкладке New выберите DLL Wizard. Автоматически будет создан модуль – пустой шаблон будущей DLL.

Синтаксис DLL

Для того, чтобы построить DLL, выберите Project -> Build Имя_проекта.

Видимость функций и процедур

Функции и процедуры могут быть локальными и экспортируемыми из DLL.

Локальные

Локальные функции и процедуры могут быть использованы внутри DLL. Они видны только внутри библиотеки и ни одна программа не может их вызывать извне.

Экспортируемые

Экспортируемые функции и процедуры могут быть использованы за пределами DLL. Другие программы могут вызывать такие функции и процедуры.

Исходный код выше использует экспортируемую функцию. Имя функции следует за зарезервированным словом Exports.

Загрузка DLL

В Delphi есть два вида загрузки DLL:

  • Статическая загрузка
  • Динамическая загрузка

Статическая загрузка

При запуске приложения загружается автоматически. Она остается в памяти на протяжении выполнения программы. Очень просто использовать. Просто добавьте слово external после объявления функции или процедуры.

Если DLL не будет найден, программа будет продолжать работать.

Динамическая загрузка

DLL загружается в память по мере необходимости. Ее реализация более сложная, потому что Вы сами должны загружать и выгружать ее из памяти. Память используется более экономно, поэтому приложение работает быстрее. Программист сам должен следить, чтобы все работало правильно. Для этого нужно:

  • Объявить тип описываемой функции или процедуры.
  • Загрузить библиотеку в память.
  • Получить адрес функции или процедуры в памяти.
  • Вызвать функцию или процедуру.
  • Выгрузить библиотеку из памяти.

Объявление типа, описывающего функцию

Загрузка библиотеки

Получаем указатель на функцию

Вызов функции

Выгрузка библиотеки из памяти

Динамический вызов DLL требует больше работы, но легче управлять ресурсами в памяти. Если Вы должны использовать DLL в пределах программы, тогда предпочтительнее статическая загрузка. Не забывайте использовать блок try…except и try…finally, чтобы избежать ошибок во время выполнения программы.

Экспорт строк

Созданная DLL с использованием Delphi, может быть использована и в программах, написанных на других языках программирования. По этой причине мы не можем использовать любой тип данных. Типы, которые существуют в Delphi могут отсутствовать в других языках. Желательно использовать собственных типы данных из Linux или Windows. Наша DLL может быть использована другим программистом, который использует другой язык программирования.

Можно использовать строки и динамические массивы в DLL, написанной в Delphi, но для этого нужно подключить модуль ShareMem в раздел uses в DLL и программе, которая будет ее использовать. Кроме того, это объявление должно быть первым в разделе uses каждого файла проекта.

Типов string, как мы знаем, С, С++ и других языках не существует, поэтому желательно использовать вместо них PChar.


Сразу оговорось что описанные ниже правила применимы для "крос-языковой" dll, но я очень советую если не знаете что делаете, то применять их и в случаее когда верна схема приложение(delphi) - dll(delphi).

Что можно передавать безопасно:

[const, var, out]Целочисленные(возможно только надо быть осторожным с int64/uint64 в 32 битной dll, но я не уверен)

[const, var, out]Дробные single и double(real лучше не использовать)

[const, var, out]Любые указатели на элементарные типы, структуры и статические массивы

[const, var, out]WideString

Что можно возращать безопасно:

  • Любые целочисленные
  • Любые указатели

Со структурами нужно соблюдать осторожность и понимать что они могут передаваться как указатель в регистре или полностью в регистре значение. Также не мало важно выравнивание.

Перерача строк, массивов:

Никогда не передавайте и не возвращайте строки или массивы. Эти типы являются управляемыми в контексте языка Delphi, и если вы попытаетесь передавать эти типы в лучшем случаем получите AV или утечку. В худшем случае приложение может и схлопнуться.

Вы должны обеспечить обработку исключений внутри dll и ни когда не допускать их наружу. Исключения являются классами Delphi и другие языки о них ни чего не знают, из за этого поведение при исключениях может быть не предсказуемым.

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

Примеры:

Если dll не ваша:

Напиши свою длл обертку соблюдая правила и все буде хорошо

PS:

Для шарпа под рукой ни чего нет поэтому код проверял только на Delphi. И вот хорошие описание для шарпа как надо преобразовывать передачу массиов в шарпе

Читайте также: