Я могу создать постоянного клиента окна DLL (для плагина) в.NET?

1119 Было бы полезно, если бы мы могли точно видеть, что вы делаете на отправляющей стороне. Однако очевидно, что у вас есть несколько проблем.

Во-первых, в начальных recv очевидно, что вы намеревались получить только начальный объект pickle, который вы использовали для кодирования длины оставшихся байтов. Однако, что recv может также получить начальный сегмент оставшихся байтов (или даже всех оставшихся байтов, в зависимости от того, насколько он большой). Так сколько же вы должны дать начальному pickle.loads?

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

import struct
# Pickle the data to be sent
data = pickle.dumps(python_obj)
data_len = len(data)
# Pack data length into 4 bytes, encoded in network byte order
data_len_to_send = struct.pack('!I', data_len)  
# Send exactly 4 bytes (due to 'I'), then send data
conn.sendall(data_len_to_send)
conn.sendall(data)

На принимающей стороне, как сказано в исключении, pickle.loads принимает строку байтов, а не список. Поэтому частью решения этой проблемы будет объединение всех элементов списка в одну байтовую строку перед вызовом loads:

unpickled = pickle.loads(b''.join(data))

Другие проблемы на принимающей стороне: используйте len(packet), чтобы получить размер буфера. sys.getsizeof предоставляет внутреннюю память, используемую объектом bytes, которая включает в себя неопределенные накладные расходы интерпретатора и здесь не то, что вам нужно.

После recv первое, что вы должны сделать, это проверить наличие пустого буфера, который указывает конец потока (даже len(packet) == 0 или packet == '' или not packet). Это может произойти, например, если отправитель был убит до завершения отправки (или сбой сетевого соединения, или какая-то ошибка на стороне отправителя и т. Д.). В противном случае, если соединение заканчивается преждевременно, ваша программа никогда не достигнет break и, следовательно, будет в очень узком бесконечном цикле.

Итак, в целом вы можете сделать что-то вроде этого:

# First, obtain fixed-size content length
buf = b''
while len(buf) < 4:
    tbuf = recv(4 - len(buf))
    if tbuf == '':
        raise RuntimeError("Lost connection with peer") 
    buf += tbuf

# Decode (unpack) length (note that unpack returns an array)
len_to_recv = struct.unpack('!I', buf)[0]

data = []
len_recved = 0
while len_recvd < len_to_recv:
    buf = self.s.recv(min(len_to_recv - len_recvd, BUFFERSIZE))
    if buf == '':   
        raise RuntimeError("Lost connection with peer") 
    data.append(buf)
    len_recvd += len(buf)

unpickled_obj = pickle.loads(b''.join(data))

РЕДАКТИРОВАТЬ: перенесены круглые скобки

5
задан 1 January 2009 в 04:30
поделиться

6 ответов

Нет, C# DLLs управляются, означая, что Вам нужен CLR, загруженный для компьютера для понимания этого. Вы смогли использовать нормальный проект C++, добавлять C++ / CLI к нему (настройки проекта), использовать DLL C# с ним, затем писать основному C экспортируемую функцию, которые переносят его.

Это было бы первой вещью, которую я попробую.

1
ответ дан 14 December 2019 в 01:19
поделиться

Мне удалось стать что я разыскиваемым после довольно замысловатого набора шагов:

На стороне C#:

  1. Я создал класс C# с интерфейсом
  2. сделанный этим COM видимый,
  3. Подписанный блок с файлом ключей строгого имени
  4. Используемый gacutil для добавления блока к GAC
  5. Зарегистрированный это в инструменте REGASM и произведенный tlb файл библиотеки типов.

Затем я создал DLL MFC, выставляющий функции, которые я должен был экспортировать для сменного интерфейса. Затем использование #import директивы в моем C++ кодирует для загрузки в ранее упомянутом tlb файле. Это генерирует тупик, таким образом, я могу легко звонить в свой код C# от C++ через COM.

Результат, кажется, работает отлично, и производительность мгновенна (это немного удивительно, я предположил, что загрузка CLR наверху будет примечательна).

Загрузка CLR в это конкретное приложение не является действительно проблемой, но я обеспокоен проблемами управления версиями с другими плагинами. Это - действительно беспокойство когда я делающий это на всем протяжении COM?

4
ответ дан 14 December 2019 в 01:19
поделиться

Вы не можете создать Собственный DLLs, использующий C# или любой язык платформы .NET. Платформа .NET может однако использовать Собственный DLLs, использующий P/Invoke.

Это не практическая запись собственного DLL в C# так или иначе. Вы были бы более обеспеченной записью DLL в C или C++ вместо этого.

Если Вы собираетесь сделать заключительную программу в языке платформы .NET (Управляемый С++, C#, .NET), то можно сделать DLL в C#, иначе не делайте.

1
ответ дан 14 December 2019 в 01:19
поделиться

К op:

Я делаю пользовательскую Дополнительную разработку для пакета, который использует старые взаимодействующие с COM блоки. Мы хотели использовать c#, но так как он зависит так в большой степени от позднего связывания, мы должны волновать использование vb.net и создать взаимодействующий через интерфейс класс как взаимодействующий с COM класс. После того как Вы преобладаете над тем препятствием, Вы являетесь обычно в значительной степени золотыми. Вся поддержка освобождает за пределами "интерфейсной" библиотеки, сделаны в C#, таким образом, это - меньше работы когда новая версия основной премьеры приложения вскоре.

Хотел бы услышать то, что Вы программируете Дополнения для, поэтому если существуют какие-либо подсказки и/или приемы, с которыми мы могли помочь Вам, мы можем сделать так, как Вы продвигаетесь.

1
ответ дан 14 December 2019 в 01:19
поделиться

При использовании Visual C++ можно создать собственный dll, который переносит функциональность, записанную в.NET dll. Если Вы знаете C++ вообще (или если Вы - быстрый ученик), он должен будет справедливо просто записать, что C++ шиммирует dll, который вызывает функции, которые Вы реализуете в блоке C#.

Но, Вы не можете сделать этого с помощью только C#.

1
ответ дан 14 December 2019 в 01:19
поделиться

Можно записать assembly/dll в C++ / CLI, который выставляет функции в как стандартный экспорт DLL. Вы могли затем использовать их в качестве прокси для методов в блоке C#, если Вы хотите.

Однако это не означает, что это - хорошая идея. Принуждение CLR загрузиться в процесс является довольно решительным шагом и тем, который сменный автор не должен вызывать на его хосте.

Например, Microsoft сильно recommeds, что авторы расширения оболочки (т.е. сменный код для Windows Explorer) не пишут те плагины (через COM) в.NET, потому что они не хотят CLR, загруженный в такой критический applicatoin.

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

1
ответ дан 14 December 2019 в 01:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: