2016-12-06 16 views
0

Я работаю над проектом (C++/cx Directx) (Universal Windows), который строится на dll, используемом в проекте UWP C#.0x88982F50: «Компонент не найден» При использовании DirectXTK CreateWICTextureFromMemory()

Я использую DirectX Toolkit для загрузки текстур.

Я уже использую его для создания текстуры из файла, но теперь мне это нужно, чтобы создать текстуру из массива байтов, который был отправлен из проекта UWP. Но при попытке использовать CreateWICTextureFromMemory(), то HRESULT говорит 0x88982F50: «Компонент не может быть найден»

Все, что я могу найти информацию об этой проблеме указывает байты не правильное изображение, но я тестировал его в UWP, там я получаю массив байтов из бингмапов (это статическое изображение карты), и я мог бы создать рабочий образ из этих байтов.

Разве annyone знает, что я делаю неправильно?

UWP C# скачать код (чтобы получить байт):

private async Task DownloadTexture() 
    { 
     byte[] buffer = null; 
     try 
     { 
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url); 
      WebResponse response = await request.GetResponseAsync(); 
      using (Stream stream = response.GetResponseStream()) 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       stream.CopyTo(ms); 
       buffer = ms.ToArray(); 
      } 
     } 
     catch (Exception exception) 
     { 
      Logger.Error($"Could not Download Texture: {exception}"); 
     } 

     _track3D.SetImage(out buffer[0], (ulong)buffer.Length); 
    } 

DiRectX код C++ (которая не):

void Track3D::SetImage(uint8_t* ddsData, size_t ddsDataSize) 
{ 
    HRESULT result = CreateWICTextureFromMemory(_d3dDevice.Get(), _d3dContext.Get(), ddsData, ddsDataSize, nullptr, _Terrain.ReleaseAndGetAddressOf()); 
    //here it goes wrong 
    //TODO: use the texture 
} 

UWP C# код тест, который работает (отображает изображение):

private async void setImage(byte[] buffer) //test 
    { 
     try 
     { 
      BitmapImage bmpImage = new BitmapImage(); 
      using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) 
      { 
       await stream.WriteAsync(buffer.AsBuffer()); 
       stream.Seek(0); 
       await bmpImage.SetSourceAsync(stream); 
      } 

      Image image = new Image(); 
      image.Source = bmpImage; 

      ((Grid)Content).Children.Add(image); 
     } 
     catch (Exception exception) 
     { 
      Logger.Error($"{exception}"); 
     } 
    } 

EDIT:

ОК, получается, что первый байт в буфере отличается от кода C++, чем это было при отправке из UWP. Когда я меняю этот первый байт на правильное значение в коде C++ (в качестве теста), текстура будет правильно создана.

Что вызывает вопрос, почему изменилось значение первого байта? (? Или то, что я сделал не так)

В соответствии с просьбой, функция setImage() выглядит в C#:

[MethodImpl] 
public void __ITrack3DPublicNonVirtuals.SetImage(out byte ddsData, [In] ulong ddsDataSize); 

(также, я просто понял, что имена параметров до сих пор «ДДС» в их имя, жаль, что изменится, что в моем коде, как это вводит в заблуждение)

+1

Можете ли вы подтвердить, что COM инициализируется на поток, который вы звоните '' CreateWICTextureFromMemory'' на? Также убедитесь, что вы используете недавнюю версию DirectXTK, поскольку она исправила некоторые проблемы состояния гоночной машины WIC для многопоточного использования. Наконец, помните, что немедленное использование контекста не является потокобезопасным. Вы можете использовать версию, которая не принимает ее, если вам не нужны микропрограммы с автогенератором, иначе вам нужен мьютекс. –

+0

Боюсь, я не знаком с тем, о чем вы говорите. Я новичок как в C++/cx, directx, так и в инструменте directx. Я давно видел «COM», но я до сих пор не знаю, что это такое. Я нашел https://msdn.microsoft.com/en-us/library/ms694363(VS.85).aspx, но мне все еще не ясно. Я предполагаю это здесь: https: //directxtk.codeplex.com/wikipage? Title = WICTextureLoader (относительно CoInitialize и прочее) относится к тому же, о чем вы говорите. Но я не знаю. – Stef

+0

Кроме того, я использовал пакет nuget directxtk_uwp версии 2016.10.6.1, и я только что обновил его до 2016.12.5.1. (Но это ничего не меняло.) – Stef

ответ

1

0x88982F50: «компонент не может быть найден»

Это WINCODEC_ERR_COMPONENTNOTFOUND, который происходит, когда WIC не может определить, какой формат кодека использовать для файла/двоичного файла. Ваша проблема заключается в неправильной передаче данных из управляемого кода.

Ваш метод Interop установлен в:

[MethodImpl] 
public void __ITrack3DPublicNonVirtuals.SetImage(out byte ddsData, [In] ulong ddsDataSize); 

С методом C++ подписи существа:

void Track3D::SetImage(uint8_t* ddsData, size_t ddsDataSize) 

Из-за out первого параметра передается как безопасного массива с длина в первом элементе.

Вместо этого вы должны использовать:

SetImage([In] byte ddsData, [In] ulong ddsDataSize); // C# 

void Track3D::SetImage(const uint8_t* ddsData, size_t ddsDataSize); // C++. 
+0

Первоначально я тоже подумал, что мне нужно добавить «const», но когда я это сделаю, я получаю «Error C4400» const uint8_t ': const/volatile отступы для этого типа не поддерживается". Кроме того, подпись метода C# не написана ни мной, ни кем-либо, она просто создается или интерпретируется так или иначе проектом UWP. Но я согласен, что «вне» кажется неправильным. – Stef

+0

вздох, я чувствую, что повторяю одни и те же ошибки снова и снова, потому что думаю, что у меня была такая же проблема некоторое время назад. Я думаю, что, возможно, я мог бы отправить массив как «const Platform :: Array ^» вместо «uint8_t *». Будет ли это работать? – Stef

+0

Да, я идиот. У меня была такая же проблема месяц назад. Если я сделаю это так, как я только что описал, «выход» превращается в «[In]» на стороне C#. Я действительно должен был увидеть это «вне» и понял, что это неправильно. Извините за беспокойство и спасибо за помощь. (Я до сих пор не понимаю, почему отправка его так, как я сделал первый байт, был некорректным, но все остальные были правильными, хотя.) – Stef