Я считаю, что в случае наследования вы должны реализовать Coding
самостоятельно. То есть вы должны указать CodingKeys
и реализовать init(from:)
и encode(to:)
как в суперклассе, так и в подклассе. WWDC видео (около 49:28, на фото ниже), вы должны вызвать супер с суперкодером / декодером.
required init(from decoder: Decoder) throws {
// Get our container for this subclass' coding keys
let container = try decoder.container(keyedBy: CodingKeys.self)
myVar = try container.decode(MyType.self, forKey: .myVar)
// otherVar = ...
// Get superDecoder for superclass and call super.init(from:) with it
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)
}
Видео, кажется, перестает показывать сторону кодирования (но это container.superEncoder()
для стороны encode(to:)
), но она работает примерно так же в вашей реализации encode(to:)
. Я могу подтвердить, что это работает в этом простом случае (см. Ниже код детской площадки).
Я все еще борюсь с каким-то нечетным поведением с гораздо более сложной моделью, которую я конвертирую из NSCoding
, у которой много новых типов (включая struct
и enum
), это демонстрирует это неожиданное поведение nil
и «не должно быть». Просто имейте в виду, что могут быть краевые случаи, связанные с вложенными типами.
Редактировать: вложенные типы, похоже, отлично работают на моей тестовой площадке; Теперь я подозреваю, что что-то не так с классами саморегуляции (подумайте о детях узлов дерева) с самим набором, который также содержит экземпляры этого класса под разными классами. Тест простого класса саморегуляции отлично декодирует (т. Е. Никаких подклассов), поэтому я теперь сосредоточиваю свои усилия на том, почему случай подкласса терпит неудачу.
Обновление 25 июня 17: Я закончил тем, что написал об этом Apple. rdar: // 32911973 - К сожалению, цикл кодирования / декодирования массива из Superclass
, который содержит элементы Subclass: Superclass
, приведет к тому, что все элементы в массиве будут декодированы как Superclass
(подкласс «init(from:)
никогда не вызывается, что приводит к потере данных или к худшему).
//: Fully-Implemented Inheritance
class FullSuper: Codable {
var id: UUID?
init() {}
private enum CodingKeys: String, CodingKey { case id }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(UUID.self, forKey: .id)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
class FullSub: FullSuper {
var string: String?
private enum CodingKeys: String, CodingKey { case string }
override init() { super.init() }
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let superdecoder = try container.superDecoder()
try super.init(from: superdecoder)
string = try container.decode(String.self, forKey: .string)
}
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(string, forKey: .string)
let superdecoder = container.superEncoder()
try super.encode(to: superdecoder)
}
}
let fullSub = FullSub()
fullSub.id = UUID()
fullSub.string = "FullSub"
let fullEncoder = PropertyListEncoder()
let fullData = try fullEncoder.encode(fullSub)
let fullDecoder = PropertyListDecoder()
let fullSubDecoded: FullSub = try fullDecoder.decode(FullSub.self, from: fullData)
Оба свойства супер- и подкласса восстанавливаются в fullSubDecoded
.
Я столкнулся с одной и той же проблемой. В моем случае у меня было два 32-битных ПК. Один с установленным .NET4.5 и другим был свежий ПК.
моя 32-разрядная cpp dll (версия режима сборки) отлично работала с установленным компьютером .NET, но не со свежим ПК, где я получил ниже error
Не удается загрузить DLL 'PrinterSettings.dll': указанный модуль не найден. (Исключение из HRESULT: 0x8007007E)
blockquote>наконец,
Я только что построил свой проект в конфигурации режима отладки, и на этот раз моя cpp dll работала нормально.
blockquote>
Вы можете использовать инструмент dumpbin для поиска необходимых DLL-зависимостей:
dumpbin /DEPENDENTS my.dll
Это скажет вам, какие DLL-файлы должны загружать DLL. Особенно обратите внимание на MSVCR * .dll. Я видел, что ваш код ошибки возникает, когда корректный Visual C ++ Redistributable не установлен.
Вы можете получить «Распространяемые пакеты Visual C ++ для Visual Studio 2013» с веб-сайта Microsoft. Он устанавливает c: \ windows \ system32 \ MSVCR120.dll
В имени файла 120 = 12.0 = Visual Studio 2013.
Будьте осторожны, чтобы у вас была правильная версия Visual Studio ( 10.0 = VS 10, 11 = VS 2012, 12.0 = VS 2013 ...) правильная архитектура (x64 или x86) для вашей целевой платформы DLL, а также вам нужно быть осторожным в сборке отладки. Отладочная сборка DLL зависит от MSVCR120d.dll, которая является отладочной версией библиотеки, которая устанавливается с помощью Visual Studio, но не с помощью распространяемого пакета.
debug
, версия RII для среды исполнения должна быть точно такой же, как и при ее создании.
– skyline75489
26 September 2016 в 08:10
Это «kludge», но вы можете хотя бы использовать его для проверки работоспособности: попробуйте жестко кодировать путь к DLL в вашем коде
[DllImport(@"C:\\mycompany\\MyDLL.dll")]
. Сказав это; в моем случае работает dumpbin /DEPENDENTS
, как было предложено @ anthony-hayward, и копирование через 32-битные версии DLL, перечисленных там в моем рабочем каталоге, решило эту проблему для меня.
Сообщение просто немного вводящий в заблуждение, потому что это не «моя» DLL, которая не может быть загружена - это зависимости
Я думаю, что ваша неуправляемая библиотека нуждается в манифесте. Здесь заключается в том, как добавить его в ваш двоичный файл. и здесь .
Таким образом, в вашем окне может быть установлено несколько версий распространяемой библиотеки, но только одно из них должно удовлетворять вашему приложению, и это может быть не по умолчанию, поэтому вам нужно сообщить системе, что нужна вашей библиотеке, поэтому манифест.
Убедитесь, что все зависимости вашей собственной DLL находятся рядом с dll или в System32
.
Убедитесь, что вы устанавливаете платформу Build Platform Target на x86 или x64, чтобы она была совместима с вашей DLL, которая может быть скомпилирована для 32-битной платформы.
Из того, что я помню в Windows, порядок поиска для dll:
C:\windows\system32 or c:\windows\SysWOW64
(для 32-битного процесса на 64 -битная коробка). Path
Кроме того, я бы проверял зависимости DLL, хост зависимостей, предоставляемый Visual Studio может помочь вам здесь, его также можно бесплатно скачать: http://www.dependencywalker.com
Попробуйте ввести полный путь к dll. Если это не сработает, попробуйте скопировать dll в папку system32.
Настройка: 32-разрядная версия Windows 7
Контекст: установлен драйвер PCI-GPIB, с которым я не смог связаться из-за вышеупомянутой проблемы.
Краткий ответ: переустановите Драйвер.
Длинный ответ: Я также использовал Dependency Walker , который идентифицировал несколько отсутствующих модулей зависимостей. Сразу же я подумал, что это была неудачная установка драйвера. Я не хотел проверять и восстанавливать каждый отсутствующий файл.
Тот факт, что я не смог найти деинсталлятор в разделе «Программы и компоненты панели управления», является еще одним показателем плохой установки. Мне пришлось вручную удалить пару * .dll в \ system32 и ключи реестра, чтобы разрешить повторную установку драйвера.
Исправлена проблема.
Неожиданная часть заключалась в том, что не всякая зависимость модули были разрешены. Тем не менее, теперь можно найти ссылку на * .dll.
DLL должна находиться в папке bin.
В Visual Studio я добавляю dll в свой проект (НЕ в ссылках, но «Добавить существующий файл»). Затем установите для свойства «Копировать в выходной каталог» значение для «Копировать, если новое».
У меня была такая же проблема, когда я развернул приложение для тестирования ПК. Проблема заключалась в разработке ПК с msvcp110d.dll
и msvcr110d.dll
, но не на тестовом ПК.
Я добавил «Слияние модуля Visual Studio C ++ 11.0 DebugCRT (x86)» в InstalledSheild, и он сработал. Надеюсь, это будет полезно для кого-то другого.
Есть одна очень забавная вещь (и имеет техническую значимость), которая может растратить ваши часы, поэтому подумал о ее совместном использовании -
Я создал проект консольного приложения ConsoleApplication1
и проект библиотеки классов ClassLibrary1
.
Весь код, который делал p / invoke, присутствовал в ClassLibrary1.dll
. Поэтому перед отладкой приложения из visual studio я просто скопировал неуправляемую сборку C ++ (myUnmanagedFunctions.dll
) в каталог \bin\debug\
проекта ClassLibrary1
, чтобы он мог быть загружен в среду выполнения CLR.
Я продолжал получать
Не удалось загрузить DLL
blockquote>в течение нескольких часов. Позже я понял, что все такие неуправляемые сборки, которые необходимо загрузить, необходимо скопировать в каталог
\bin\debug
стартового проектаConsoleApplication1
, который обычно представляет собой форму выигрыша, консольное или веб-приложение.Итак, будьте осторожны,
Current Directory
в принятом ответе на самом деле означаетCurrent Directory
основного исполняемого файла, с которого начинается процесс приложения. Похоже на очевидную вещь, но может быть и не так.Извлеченный урок - всегда помещайте неуправляемые DLL в том же каталоге, что и исполняемый файл запуска, чтобы убедиться, что его можно найти.
Если DLL и .NET-проекты находятся в одном и том же решении, и вы хотите их компилировать и запускать каждый раз, вы можете щелкнуть правой кнопкой мыши по свойствам проекта .NET, Build events, а затем добавить что-то вроде следующего в Post Командная строка события:
copy $(SolutionDir)Debug\MyOwn.dll .
Это в основном линия DOS, и вы можете настроить ее на основе того, где строится ваша DLL.
Включите ведение журнала сварки, см. этот вопрос для получения большого количества советов о том, как это сделать. Отладка проблем с загрузкой приложений смешанного режима может быть правильной болью. Регистрация слияния может быть большой помощью.