C#学习教程:使用P / Invoke从C#编组“EGLRenderResolutionScaleProperty”到ANGLE分享


使用P / Invoke从C#编组“EGLRenderResolutionScaleProperty”到ANGLE

我正在尝试使用P / Invoke让ANGLE在C#中工作。 基本上,我正在创建一个简单的2D表面,然后将其传递给skia(使用SkiaSharp)。 一切都工作,所有这一切,但我有一个问题编组PropertySet到非托管代码。

这个位工作正常:

 // the properties var props = new PropertySet(); props.Add("EGLNativeWindowTypeProperty", swapChainPanel); // the surface attributes int[] surfaceAttrs = { EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_NONE }; // create the surface surface = eglCreateWindowSurface(eglDisplay, eglConfig, props, surfaceAttrs); 

我的导入如下:

 [DllImport("libEGL.dll")] public static extern IntPtr eglCreateWindowSurface( IntPtr dpy, IntPtr config, [MarshalAs(UnmanagedType.IInspectable)] object win, int[] attrib_list); 

当我尝试为高分辨率屏幕设置缩放时,问题就出现了。 这应该“应该”起作用:

 var scale = PropertyValue.CreateSingle(2); props.Add("EGLRenderResolutionScaleProperty", scale); 

它在使用C ++时有效,但在C#中则无效。 我想我已经明白了实际值没有被正确编组的事实。 这是因为在ANGLE代码中进行调试时,它会在这里消失:

 ComPtr propertyValue; ABI::Windows::Foundation::PropertyType propertyType; // ... result = propertyValue->get_Type(&propertyType); 

https://github.com/Microsoft/angle/blob/54b1fd01f7fddcd7011d5a04e9259edace8a13da/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp#L242

运行时exception是:

运行时检查失败#0 – 在函数调用中未正确保存ESP的值。 这通常是调用使用一个调用约定声明的函数和使用不同调用约定声明的函数指针的结果。

有没有提示或解决方案?

以下是我的所有参考代码: https : //gist.github.com/mattleibow/eacb9c9e87f306b218d99c713c532a82

原始ANGLE问题: https : //github.com/Microsoft/angle/issues/89

编辑

经过进一步调查,我发现由于某种原因,C#中的PropertyValue与C ++中的相同类型(通过Windows运行时组件)不同。

我试过这个:

 static PropertySet^ CreateSurface(SwapChainPanel^ panel, float scale) { PropertySet^ surfaceCreationProperties = ref new PropertySet(); surfaceCreationProperties->Insert(L"EGLNativeWindowTypeProperty", panel); Object^ scaleVal = PropertyValue::CreateSingle(scale); surfaceCreationProperties->Insert(L"EGLRenderResolutionScaleProperty", scaleVal); return surfaceCreationProperties; } 

此方法在C ++中创建了一个PropertySet ,然后将其返回给C#。 这很好用,我的ANGLE会话都很好。

现在,如果我更改代码以直接返回PropertyValue::CreateSingle(scale) ,则会再次失败。 如果我将PropertyValue.CreateSingle(scale)从C#传递到此C ++方法,我发现对象不相似。

在调试器本地中,我得到了在C#中构造的对象:

 0x09f10ba4  Platform::Object ^ 

如果对象是用C ++构造的,我会得到:

 0x019162e8 2.00000000 Platform::Object ^ {WinTypes.dll!Windows::Foundation::Value<Windows::Foundation::ValueScalar >} 

对象不应该是相同的,因为它们是相同的类型? 更可怕的是,如果我将此值传递到边界,则类型会发生变化。

删除了编辑2并将其设置为答案。

我没有直接回答你的问题。

但是,一种经过validation的替代方法是创建一个C ++ WindowsRuntime组件包装器项目,也就是说,使用C ++ / CLI(或CXX,我应该说?)来进行互操作。

您可以公开如下方法,根据您的需要公开API。

 void InitializeEGL(Windows::UI::Core::CoreWindow^ window); void InitializeEGL(Windows::UI::Xaml::Controls::SwapChainPanel ^ window); 

或者,如果你想要更精细的粒度,在C ++ WinRT组件中声明如下所示,

 void EglCreateWindowSurface(Platform::IntPtr display, Platform::IntPtr config, Windows::Foundation::Collections::PropertySet^ propertySet); 

这个小技巧将使您能够解决C#封送问题,并且我已经validation了它的工作原理。

我将继续研究C#互操作方法。

在做了一些搜索之后,我发现最好(也是唯一)这样做的方法是创建一个Windows运行时组件。

因为我没有对组件的“硬”引用 – 这个库必须在没有ANGLE存在的情况下工作。 我选择了一个带有C API的小组件,以便我可以在需要时进行P / Invoke。 这是我在C ++中的方法:

 void PropertySetInterop_AddSingle(ABI::Windows::Foundation::Collections::IPropertySet* propertySet, HSTRING key, float scale) { using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; ComPtr propSet = propertySet; ComPtr> map; propSet.As(&map); ComPtr propValueFactory; GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), &propValueFactory); ComPtr valueInspectable; propValueFactory->CreateSingle(scale, &valueInspectable); boolean replaced; map->Insert(key, valueInspectable.Get(), &replaced); } 

我在这里使用COM,以便我可以在C / C ++代码中使用它。 我的P / Invoke代码是这样的:

上述就是C#学习教程:使用P / Invoke从C#编组“EGLRenderResolutionScaleProperty”到ANGLE分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

 internal static class PropertySetInterop { public static void AddSingle(PropertySet properties, string key, float value) { PropertySetInterop_AddSingle(properties, key, value); } public static void AddSize(PropertySet properties, string key, float width, float height) { PropertySetInterop_AddSize(properties, key, width, height); } private const string libInterop = "SkiaSharp.Views.Interop.UWP.dll"; [DllImport(libInterop)] private static extern void PropertySetInterop_AddSingle( [MarshalAs(UnmanagedType.IInspectable)] object properties, [MarshalAs(UnmanagedType.HString)] string key, float value); [DllImport(libInterop)] private static extern void PropertySetInterop_AddSize( [MarshalAs(UnmanagedType.IInspectable)] object properties, [MarshalAs(UnmanagedType.HString)] string key, float width, float height); } 

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/960104.html

发表评论

邮箱地址不会被公开。 必填项已用*标注