尝试通过互操作将C ++转换为C# [英] Attempting to convert C++ into C# with interop

查看:108
本文介绍了尝试通过互操作将C ++转换为C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序可以在C ++中调用EGL.我想在C#中进行相同的调用,但是在C#中似乎没有一个等效的概念.

I've got a program that calls to EGL in C++. I want to make the same call in C#, but there doesn't seem to be an equivalent concept in C#.

当执行上下文输入C ++ EGL代码时,出现读取/写入访问被拒绝错误.

I'm getting a read/write access denied error when the execution context enters the C++ EGL code.

这是我要转换为C#的C ++程序中的代码:

This is the code in the C++ program that I'm trying to convert to C#:

PropertySet^ surfaceCreationProperties = ref new PropertySet();
surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), somethingOtherThanAWindow);

mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes));

我有一个C#类,它将C#EGL调用转换为C ++调用.我相信C ++是不受管理的,尽管我不知道该如何确定.

I have a C# class which converts C# EGL calls into C++ calls. I believe the C++ is unmanaged, though I wouldn't know how to tell you for certain.

C#类如下:

public static IntPtr CreateWindowSurface(IntPtr dpy, IntPtr config, IntPtr win, int[] attrib_list)
{
    IntPtr retValue;

    unsafe {
        fixed (int* p_attrib_list = attrib_list)
        {
            retValue = Delegates.peglCreateWindowSurface(dpy, config, win, p_attrib_list);
        }
    }
    return (retValue);
}

更多的代码可以在这里看到: https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/Egl.VERSION_1_0.cs#L751

More of that code can be seen here: https://github.com/luca-piccioni/OpenGL.Net/blob/master/OpenGL.Net/Egl.VERSION_1_0.cs#L751

您可能会注意到此方法有一个IntPtr win,这是我传递PropertySet的地方.通常,我相信这将是System.Windows.Forms.Control,但是在C ++ EGL代码中进行了一些检查以查看它是否为PropertySet.

You may notice that this method has an IntPtr win -- this is where I'm passing the PropertySet. Typically I believe this would be a System.Windows.Forms.Control, but some checking is done in the C++ EGL code to see if it is, or if it's a PropertySet.

被调用的C ++方法是这样的:

The C++ method that is being called is this:

EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)

更多信息请参见: https://github.com/Microsoft/angle/blob/ms-holographic-experimental/src/libGLESv2/entry_points_egl.cpp#L241

如您所见,C ++方法期望使用EGLNativeWindowType.我不确定IInspectable和PropertSet之间的关系是什么-可以强制转换似乎很奇怪.

As you can see, the C++ method is expecting an EGLNativeWindowType. I'm not exactly sure what the relationship to that is between an IInspectable, and a PropertSet - it seems strange that this can be casted.

EGLNativeWindowType具有以下类型定义:

EGLNativeWindowType has the following type definition:

typedef HWND EGLNativeWindowType;

这暗示它必须是某种窗口句柄.我不明白如何将PropertySet用作窗口句柄.

Which implies it has to be some sort of window handle. I don't understand how a PropertySet could be a window handle.

我怀疑主要问题在于选择正确类型的对象以传递给C#EGL实现. PropertySet似乎是正确的选择,但reinterpret_cast确实让我失望了.

I suspect the main problem is around choosing the correct type of object to pass to the C# EGL implementation. PropertySet seems like it might be the right choice, but the reinterpret_cast is really throwing me off.

有人可以引导我完成这个过程吗?

Can anyone walk me through this?

推荐答案

通常,我认为这将是System.Windows.Forms.Control ...

Typically I believe this would be a System.Windows.Forms.Control...

这是一个痛苦的错误假设.要理解打字,需要写三本书,这在SO答案中很难做到.如果您实际上打算从Winforms应用程序中执行此操作,然后立即停止操作,那将永远无法进行.

It is a painfully wrong assumption. Making sense of the typing requires writing three books, pretty hard to do in an SO answer. If you actually intend to do this from a Winforms app then stop right now, that can never work.

OpenGL使用非常松散类型,其api函数的参数只不过是原始指针void*而已.这使它非常灵活,但是指针实际指向的真的很重要.如果客户端程序和视频适配器接口在最简单的方式上不同意,那么您的程序将构建得很好,但将在运行时崩溃并以完全无法诊断的方式刻录.结果就是Microsoft放弃OpenGL并决定创建自己的DirectX的主要原因.

OpenGL uses very loose typing, the arguments to their api functions are nothing much more than void*, a raw pointer. Which makes it very flexible but it is really important what the pointer actually points to. If the client program and the video adapter interface don't agree about that in the slightest way then your program will build just fine but will crash and burn in completely undiagnosable way at runtime. A major reason why Microsoft abandoned OpenGL and decided to create their own, DirectX was the result.

虽然也使用指针,但是它们是更聪明的一种,它们在运行时支持类型发现.它们是IUnknown指针,其QueryInterface()方法允许找出对象是否支持特定的预期接口.您在此处看到的风格与指针完全相同,IInspectable是比IUnknown稍微聪明的版本,并且所有WinRT类都实现了基本接口.您确实要这样做,因为它是ANGLE端口所期望的,因此必须传递IInspectable *.

Which uses pointers as well but they are the smarter kind, they support type discovery at runtime. They are IUnknown pointers, its QueryInterface() method permits finding out if an object supports a specific expected interface. The flavor you see being used here is the exact same kind of pointer, IInspectable is a slightly smarter version than IUnknown and the base interface implemented by all WinRT classes. You really do have to pass an IInspectable* since that is what the ANGLE port expects.

通常希望您可以传递ICoreWindow接口指针并完成操作,这就是窗口的WinRT接口.但是,渲染器不仅需要ICoreWindow,还需要更多信息.不确定原因,我认为这与WinRT中的分辨率独立性有关. 还需要知道表面尺寸和比例因子.

You'd generally expect that you could just pass an ICoreWindow interface pointer and be done with it, that's the WinRT interface for a window. The renderer however requires more information than just the ICoreWindow. Not exactly sure why, I think it has something to do with resolution Independence in WinRT. It also needs to know the surface size and scaling factor.

问题是,OpenGL无法传递该信息.因此,Microsoft程序员使用了一个非常棘手的技巧,而不是添加一个函数来传递此信息,他放弃了使用传递任何IInspectable *的能力,而是传递了一个IMap<String^, IInspectable*>指针.基本上是一个属性包,位于ANGLE端口的CoreWindowNativeWindow.cpp通过其CoreWindowNativeWindow :: initialize()函数再次从该包中挖掘属性.

Problem is, OpenGL doesn't have a way to pass that info. So the Microsoft programmer used a very hokey hack, instead of adding a function to pass this info he ab/used the ability to pass any kind of IInspectable*, he passes a IMap<String^, IInspectable*> pointer. Basically a property bag, CoreWindowNativeWindow.cpp in the ANGLE port digs the properties out of the bag again in its CoreWindowNativeWindow::initialize() function.

PropertySet是实现IMap<K, V>的C ++语言投影中的具体类.请注意,它特定于C ++,在C#中,您应该使用Dictionary<string, IntPtr>代替. CLR中内置的语言投影会自动将托管字典映射到本机IMap接口.

PropertySet is a concrete class in the C++ language projection that implements IMap<K, V>. Do note it is specific to C++, in C# you'd use a Dictionary<string, IntPtr> instead. The language projection built into the CLR automatically maps a managed dictionary to the native IMap interface.

哦,欢乐,更多的IntPtrs. IInspectable *完全隐藏在您在C#中使用的语言投影中,这并不容易.我98%确信您可以使用元帅.GetIUnknownForObject(),以获取有效的指针,即使它的味道不正确.由于C ++代码执行正确的操作并使用QueryInterface :),之后必须调用Marshal.Release()进行清理,否则将导致内存泄漏.

Oh joy, more IntPtrs. IInspectable* is completely hidden in the language projection you use in C#, that doesn't make it easy. I'm 98% sure that you can use Marshal.GetIUnknownForObject() to obtain a pointer that works, even though it is wrong flavor. Since the C++ code does the right thing and uses QueryInterface :) You must call Marshal.Release() afterwards to clean up, not doing so causes a memory leak.

请注意,您做错事有很强的含义.我想您是,Microsoft仅出于一个原因提供了ANGLE分支.他们试图使公司轻松将其iOS游戏移植到WinRT/UWP. Kinda必须为商店提供顾客喜欢的游戏. ANGLE端口仅旨在从以ObjectiveC或C ++开头的代码(用于编写这些游戏的语言)中轻松使用.

Do note that there are strong overtones of you doing the wrong thing. I think you are, Microsoft provided this ANGLE fork only for one reason. They tried to make it easy for companies to port their iOS game to WinRT/UWP. Kinda necessary to fill the store with the kind of games that customers like. The ANGLE port was only ever intended to be easy to use from code that started in ObjectiveC or C++, the kind of languages used to write these games.

他们可以使使用Java语言或C#等语言的库变得更加容易,但并非如此,因为没有必要.如果必须将使用OpenGL的C ++代码转换为C#,那么当您使用DirectX时,很有可能会更好.这种类型的映射会遇到更多其他功能的麻烦,并且会厌倦实验性的HoloLens端口.

They could have made it a lot easier to use the library from languages like Javascript or C#, they didn't because it wasn't necessary. If you have to translate a metric mile of C++ code that uses OpenGL to C# then it is pretty likely you'd be much better off when you use DirectX instead. Expect more of this type mapping trouble with other functions and be weary of an experimental HoloLens port.

这篇关于尝试通过互操作将C ++转换为C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆