在本机 Rust 插件中使用从 Unity 接收的 ID3D11Texture2D 指针会导致调用方法时出错

问题描述 投票:0回答:1

我正在用 Rust 创建一个 Unity 原生插件。

由于我需要在 Rust 中接收 ID3D11Texture2D,所以我决定使用 windows-rs crate 版本 0.56.0。

统一代码

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEngine;
    
    public class DesktopCapture : MonoBehaviour
    {
        [DllImport("texture2d_user", EntryPoint = "modify_texture")]
        static extern void ModifyTexture(IntPtr texptr);
    
        void Start()
        {
            var tex = Texture2D.normalTexture;
            ModifyTexture(tex.GetNativeTexturePtr());
        }
    }

Rust 代码

    use windows::core::IUnknown;
    use windows::Win32::Graphics::Direct3D11::*;
    
    #[no_mangle]
    pub extern "C" fn modify_texture(texptr: *mut IUnknown) {
    
        let texture: *mut ID3D11Texture2D = texptr.cast::<ID3D11Texture2D>();
        let dimension: D3D11_RESOURCE_DIMENSION = unsafe { (*texture).GetType() };
    
        ()
    }

虽然参数传递顺利,但在 ID3D11Texture2D 上调用 GetType 方法导致了 Segmentation Failure 错误。

我想知道如何解决这个问题。预先感谢您的帮助。

为了确定问题是由 Unity 还是 Rust 引起,我用 C++ 创建了一个本机插件,并用它来创建 ID3D11Texture2D。调用这些方法没有任何问题,所以我相信问题不在于 Unity。

Unity 编辑器日志

Received signal SIGSEGV
Obtained 26 stack frames
0x00007ffadcdc1020 (texture2d_user) texture2d_user::modify_texture (at C:/Users/sabro/source/testproject/texture2d_user/src/lib.rs:8)
0x000001ce154eb96a (Mono JIT Code) (wrapper managed-to-native) DesktopCapture:ModifyTexture (intptr)
0x000001ce154eb573 (Mono JIT Code) DesktopCapture:Start () (at C:/Users/sabro/source/testproject/DesktopCapture/Assets/DesktopCapture.cs:17)
0x000001cdef27a488 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007ffadf74e274 (mono-2.0-bdwgc) mono_jit_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/mini/mini-runtime.c:3445)
0x00007ffadf68eb74 (mono-2.0-bdwgc) do_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3066)
0x00007ffadf68ed0c (mono-2.0-bdwgc) mono_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3113)
0x00007ff78895a824 (Unity) scripting_method_invoke
0x00007ff788938944 (Unity) ScriptingInvocation::Invoke
0x00007ff78892715b (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
0x00007ff788927266 (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
0x00007ff7889212c2 (Unity) MonoBehaviour::DelayedStartCall
0x00007ff7883c2aa4 (Unity) DelayedCallManager::Update
0x00007ff7885f2c59 (Unity) `InitPlayerLoopCallbacks'::`2'::EarlyUpdateScriptRunDelayedStartupFrameRegistrator::Forward
0x00007ff7885d291c (Unity) ExecutePlayerLoop
0x00007ff7885d2a98 (Unity) ExecutePlayerLoop
0x00007ff7885d9375 (Unity) PlayerLoop
0x00007ff78959cd2f (Unity) PlayerLoopController::InternalUpdateScene
0x00007ff789594513 (Unity) PlayerLoopController::EnterPlayMode
0x00007ff7895a4887 (Unity) PlayerLoopController::SetIsPlaying
0x00007ff7895a7f50 (Unity) Application::TickTimer
0x00007ff789a1e51a (Unity) MainMessageLoop
0x00007ff789a23d80 (Unity) WinMain
0x00007ff78ae07fee (Unity) __scrt_common_main_seh
0x00007ffbd02e7344 (KERNEL32) BaseThreadInitThunk
0x00007ffbd04226b1 (ntdll) RtlUserThreadStart
unity-game-engine rust directx
1个回答
0
投票

看起来您的

.cast()
正在调用
<*mut T>::cast
而不是
<IUnknown as Interface>::cast
。前者只是一个直指针转换,而后者则经过
QueryInterface
。赠品是
Interface::cast
返回
Result<T>
,但您的代码直接将结果分配给
*mut ID3D11Texture2D
变量。
Interface::cast
甚至没有资格被调用,因为它需要
&self
但你在原始指针上调用
.cast()

windows
箱中,像
IUnknown
这样的接口类型实际上已经是一个指针:我们在 C 或 C++ 中编写
IUnknown*
,而在 Rust 中只编写
IUnknown
。在通过 FFI 调用的 Rust 函数中,您的接口参数应输入
*mut c_void
,然后您可以使用
Interface::from_raw_borrowed
将它们转换为接口类型。

use std::ffi::c_void;
use windows::core::IUnknown;
use windows::Win32::Graphics::Direct3D11::*;

#[no_mangle]
pub extern "C" fn modify_texture(texptr: *mut c_void) {
    let texptr = IUnknown::from_raw_borrowed(&texptr).expect("got a null texture pointer");
    let texture: ID3D11Texture2D = texptr.cast::<ID3D11Texture2D>().expect("object doesn't implement ID3D11Texture2D");
    let dimension: D3D11_RESOURCE_DIMENSION = unsafe { texture.GetType() };
}
© www.soinside.com 2019 - 2024. All rights reserved.