Создание dll в delphi 7 для 1с
Есть 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 так:
В полях 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. И вот хорошие описание для шарпа как надо преобразовывать передачу массиов в шарпе
Читайте также: