#c# #c #windows #dll
Вопрос:
У меня есть требование, при котором двум отдельным приложениям необходимо получить доступ к объекту, содержащемуся в библиотеке DLL, и изменить его (вся логика управления приложением написана на C и работает из библиотеки DLL). Исполняемый файл пользовательского интерфейса (с минимальной логикой, написанный на C ) использует эту библиотеку DLL и взаимодействует с основной библиотекой логики управления. Я хочу добавить дополнительный exe-файл (написанный на C#) для запуска нескольких веб-служб, которым также потребуется доступ к одному и тому же объекту, содержащемуся в DLL.
Комментарии:
1. Все возможно при наличии достаточного количества времени, денег и лептонов.
2. Когда вы говорите «один и тот же объект», должны ли они видеть изменения друг друга или конкретно работать независимо?
3. Библиотека DLL содержит очень большое приложение, с которым exe-файл может взаимодействовать через посредника pub/sub. Мне понадобится доступ к этому объекту брокера из обоих исполняемых файлов, чтобы они могли получить доступ к одним и тем же данным.
4. Ваш вопрос о том, как обмениваться данными между двумя приложениями? Если это так, то общая память может быть одним из подходов, но для этого существует множество способов (очереди, файлы, API и т. Д.). Вы не можете обмениваться данными, загружая общую библиотеку dll.
Ответ №1:
Да, это называется общей памятью. DLL необходимо вызвать CreateFileMapping, чтобы выделить область памяти для совместного использования. Затем вызовите MapViewOfFile, чтобы хорошо … отобразить файл в память. Затем несколько процессов могут получить доступ к этой сопоставленной памяти через ее имя.
Комментарии:
1. Я изучал это, но, насколько я понимаю, вы не можете просто отобразить весь объект в общую память, верно? Данные, генерируемые этим объектом, будут постоянно обновляться и должны быть прочитаны обоими приложениями одновременно.
2. Технически вы можете отобразить весь объект в общую память, если это то, что вы действительно хотите сделать, но это становится немного сложнее, потому что вам нужно изучить формат переносимых файлов Windows, и этот метод обычно используется в «теневых» приложениях. Но я думаю, что вы хотите просто загрузить библиотеку dll и сопоставить ее с памятью.. Это можно сделать и без библиотеки dll, но, по сути, один процесс не может загрузить один и тот же экземпляр библиотеки dll из другого процесса, это будут два отдельных экземпляра
3. Но да, область общей памяти, отображаемая любым процессом или библиотекой dll, может быть доступна другим процессам/библиотекам DLL
Ответ №2:
Это вопрос не о c как таковом, а о том, как ваша операционная система работает с общими библиотеками. Исходя из моего опыта изучения поведения загрузчика приложений в системах Solaris, ответ-нет. Я предполагаю, что за поведением Solaris следуют Windows, Linux и т. Д., Но я полагаю, что может существовать экзотическая операционная система, которая просто хочет, чтобы вы попросили (я смотрю на вас QNX).
В принципе, если вы создадите глобальную переменную, скажем:
int foo = 5;
и скомпилируйте свою библиотеку dll и проанализируйте содержимое вашей библиотеки dll, вы увидите, что foo включен в какой-то раздел данных для чтения/записи.
Поскольку раздел предназначен для чтения/записи, когда exe-файл запускается и загружает dll, операционная система создаст копию этого раздела для exe-файла. Теперь ваш exe-файл может изменить значение на любое значение int, которое он хочет, но он изменяет только свою копию foo.
Если вы запустите другой exe-файл, он тоже загрузит библиотеку dll и тоже получит копию раздела. Этот exe-файл будет иметь собственную копию foo, и изначально он будет установлен на 5.
Разделы только для чтения ведут себя по-другому, поэтому, если бы вы определили foo следующим образом:
static const int foo = 5;
Он окажется в разделе dll, доступном только для чтения, и каждый исполняемый файл будет ссылаться на один и тот же файл в памяти. Это не позволяет вам делать то, что вы пытаетесь сделать, но это приятно знать, так как это экономит память. Хорошее эмпирическое правило состоит в том, чтобы делать все static
и const
когда это возможно.
Комментарии:
1. Это правильно, но процессы могут обращаться к общей памяти, которая на самом деле не является двумя процессами, использующими один и тот же экземпляр dll. Но это обходной путь
2. Могли бы вы порекомендовать какие-либо альтернативные подходы? -Возможно ли запустить 2 EXE-файла в рамках одного и того же процесса? -Допускает ли дочерний процесс какую-либо степень наследования доступа к памяти? -Было бы хорошей идеей сделать второй exe-файл (в настоящее время фоновая служба) dll и загрузить его из основной библиотеки dll
3. @ScottFraser из того, что я собрал, у вас есть сложная логика, хранящаяся в библиотеке DLL, вы хотите инициализировать объект в библиотеке DLL и использовать этот объект в качестве службы для нескольких дочерних процессов. Почему бы не обернуть объект вокруг API и не выполнить вызовы RPC для взаимодействия с API? Взгляните на gRPC grpc.io .