Внешняя DLL записывается на C и используется в C # [дубликат]

Я считаю, что в случае наследования вы должны реализовать 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.

88
задан Drew Noakes 29 July 2012 в 10:10
поделиться

14 ответов

Я столкнулся с одной и той же проблемой. В моем случае у меня было два 32-битных ПК. Один с установленным .NET4.5 и другим был свежий ПК.

моя 32-разрядная cpp dll (версия режима сборки) отлично работала с установленным компьютером .NET, но не со свежим ПК, где я получил ниже error

Не удается загрузить DLL 'PrinterSettings.dll': указанный модуль не найден. (Исключение из HRESULT: 0x8007007E)

наконец,

Я только что построил свой проект в конфигурации режима отладки, и на этот раз моя cpp dll работала нормально.

1
ответ дан Abu Muhammad 23 August 2018 в 02:47
поделиться

Вы можете использовать инструмент 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, но не с помощью распространяемого пакета.

30
ответ дан Anthony Hayward 23 August 2018 в 02:47
поделиться
  • 1
    добавление перераспределяемых VS C ++ было для меня! необходимо v10.0 (2010). Спасибо много! – Thiago Silva 9 September 2014 в 16:44
  • 2
    Есть ли способ узнать, нужны ли 64-разрядные или 32-разрядные версии распространяемых материалов? – BVB 7 January 2015 в 03:46
  • 3
    dumpbin / ALL скажет вам, является ли my.dll x86 x64 – Anthony Hayward 10 April 2015 в 16:51
  • 4
    Для тех, кто по-прежнему страдает от этой проблемы, если вы используете двоичный файл debug, версия RII для среды исполнения должна быть точно такой же, как и при ее создании. – skyline75489 26 September 2016 в 08:10

Это «kludge», но вы можете хотя бы использовать его для проверки работоспособности: попробуйте жестко кодировать путь к DLL в вашем коде

[DllImport(@"C:\\mycompany\\MyDLL.dll")]

. Сказав это; в моем случае работает dumpbin /DEPENDENTS, как было предложено @ anthony-hayward, и копирование через 32-битные версии DLL, перечисленных там в моем рабочем каталоге, решило эту проблему для меня.

Сообщение просто немного вводящий в заблуждение, потому что это не «моя» DLL, которая не может быть загружена - это зависимости

3
ответ дан Black 23 August 2018 в 02:47
поделиться

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

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

2
ответ дан Community 23 August 2018 в 02:47
поделиться

Убедитесь, что все зависимости вашей собственной DLL находятся рядом с dll или в System32.

4
ответ дан Felice Pollano 23 August 2018 в 02:47
поделиться

Убедитесь, что вы устанавливаете платформу Build Platform Target на x86 или x64, чтобы она была совместима с вашей DLL, которая может быть скомпилирована для 32-битной платформы.

2
ответ дан Grantly 23 August 2018 в 02:47
поделиться

Из того, что я помню в Windows, порядок поиска для dll:

  1. Current Directory
  2. Системная папка, C:\windows\system32 or c:\windows\SysWOW64 (для 32-битного процесса на 64 -битная коробка).
  3. Чтение из переменной среды Path

Кроме того, я бы проверял зависимости DLL, хост зависимостей, предоставляемый Visual Studio может помочь вам здесь, его также можно бесплатно скачать: http://www.dependencywalker.com

78
ответ дан Graviton 23 August 2018 в 02:47
поделиться
  • 1
    обнаружил недостаток некоторых зависимостей (Oracle и некоторые DLL из IE). Нужно установить Oracle, так как от меня зависит dll. Тогда я буду знать :) Нашел проблему с DependencyWalker;) – Ingimar Andresson 25 January 2012 в 15:48
  • 2
    Не беспокойтесь, это спасло много часов головы, царапающих меня, отличный инструмент! :-) – display101 25 January 2012 в 15:59
  • 3
    +1 Киту Халлигану за предложение DependencyWalker. Он сказал мне, что не все зависимости имеют один и тот же тип процессора (x86 / x64). Я скопировал все файлы с таким же типом процессора в папку bin моего приложения, и это решило проблему. – DiligentKarma 16 May 2013 в 18:58
  • 4
    Каждая DLL, которую я могу найти в моей системе, имеет DependencyWalker, утверждающий, что есть ошибка с разными типами ЦП - даже System.Web.Mvc.dll. Здесь есть какая-то ложная тревога. – PandaWood 3 July 2013 в 00:41
  • 5
    В моем случае проблема заключалась в попытке загрузить C ++ DLL, скомпилированную для Debug. Для этого требуется время отладки C ++, что означает, что вам нужно установить Visual Studio. Или перекомпилируйте DLL для выпуска и установите дистрибутив C ++. – RenniePet 29 April 2014 в 01:50

Попробуйте ввести полный путь к dll. Если это не сработает, попробуйте скопировать dll в папку system32.

10
ответ дан Headpuster 23 August 2018 в 02:47
поделиться

Настройка: 32-разрядная версия Windows 7

Контекст: установлен драйвер PCI-GPIB, с которым я не смог связаться из-за вышеупомянутой проблемы.

Краткий ответ: переустановите Драйвер.

Длинный ответ: Я также использовал Dependency Walker , который идентифицировал несколько отсутствующих модулей зависимостей. Сразу же я подумал, что это была неудачная установка драйвера. Я не хотел проверять и восстанавливать каждый отсутствующий файл.

Тот факт, что я не смог найти деинсталлятор в разделе «Программы и компоненты панели управления», является еще одним показателем плохой установки. Мне пришлось вручную удалить пару * .dll в \ system32 и ключи реестра, чтобы разрешить повторную установку драйвера.

Исправлена ​​проблема.

Неожиданная часть заключалась в том, что не всякая зависимость модули были разрешены. Тем не менее, теперь можно найти ссылку на * .dll.

1
ответ дан icernos 23 August 2018 в 02:47
поделиться

DLL должна находиться в папке bin.

В Visual Studio я добавляю dll в свой проект (НЕ в ссылках, но «Добавить существующий файл»). Затем установите для свойства «Копировать в выходной каталог» значение для «Копировать, если новое».

10
ответ дан Jeremy Thompson 23 August 2018 в 02:47
поделиться

У меня была такая же проблема, когда я развернул приложение для тестирования ПК. Проблема заключалась в разработке ПК с msvcp110d.dll и msvcr110d.dll, но не на тестовом ПК.

Я добавил «Слияние модуля Visual Studio C ++ 11.0 DebugCRT (x86)» в InstalledSheild, и он сработал. Надеюсь, это будет полезно для кого-то другого.

2
ответ дан kakopappa 23 August 2018 в 02:47
поделиться

Есть одна очень забавная вещь (и имеет техническую значимость), которая может растратить ваши часы, поэтому подумал о ее совместном использовании -

Я создал проект консольного приложения ConsoleApplication1 и проект библиотеки классов ClassLibrary1.

Весь код, который делал p / invoke, присутствовал в ClassLibrary1.dll. Поэтому перед отладкой приложения из visual studio я просто скопировал неуправляемую сборку C ++ (myUnmanagedFunctions.dll) в каталог \bin\debug\ проекта ClassLibrary1, чтобы он мог быть загружен в среду выполнения CLR.

Я продолжал получать

Не удалось загрузить DLL

в течение нескольких часов. Позже я понял, что все такие неуправляемые сборки, которые необходимо загрузить, необходимо скопировать в каталог \bin\debug стартового проекта ConsoleApplication1, который обычно представляет собой форму выигрыша, консольное или веб-приложение.

Итак, будьте осторожны, Current Directory в принятом ответе на самом деле означает Current Directory основного исполняемого файла, с которого начинается процесс приложения. Похоже на очевидную вещь, но может быть и не так.

Извлеченный урок - всегда помещайте неуправляемые DLL в том же каталоге, что и исполняемый файл запуска, чтобы убедиться, что его можно найти.

4
ответ дан RBT 23 August 2018 в 02:47
поделиться
  • 1
    Это исправлено для меня тоже. Чувствует себя странно, чтобы разместить DLL в основном проекте вместо проекта, который на самом деле их использует, хотя ... – Sean Duggan 13 November 2017 в 14:44

Если DLL и .NET-проекты находятся в одном и том же решении, и вы хотите их компилировать и запускать каждый раз, вы можете щелкнуть правой кнопкой мыши по свойствам проекта .NET, Build events, а затем добавить что-то вроде следующего в Post Командная строка события:

copy $(SolutionDir)Debug\MyOwn.dll .

Это в основном линия DOS, и вы можете настроить ее на основе того, где строится ваша DLL.

2
ответ дан SharpC 23 August 2018 в 02:47
поделиться

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

2
ответ дан Community 23 August 2018 в 06:45
поделиться
Другие вопросы по тегам:

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