我正在将现有的基于VS2008的C ++ / CLI项目(更具体地说,CefSharp)升级到VS2012,同时面临一些挑战。为避免依赖VS2008进行编译,我已将项目升级为目标.NET Framework 4.0。
一切都很好,项目编译正确,但是当我运行它并尝试创建一个WebView实例时,我得到以下TypeLoadException:
方法'CefSharp.Wpf.WebView'中的方法'SetCursor'来自程序集'CefSharp.Wpf,Version = 1.25.0.35385,Culture = neutral,PublicKeyToken = null'没有实现。“:”CefSharp .Wpf.WebView“
显然,我已经非常仔细地研究了WebView.h和WebView.cpp。他们的内容是(相关部分):
public ref class WebView sealed : public ContentControl, IRenderWebBrowser
{
public:
virtual void SetCursor(CefCursorHandle cursor);
}
实施:
void WebView::SetCursor(CefCursorHandle cursor)
{
SafeFileHandle^ handle = gcnew SafeFileHandle((IntPtr)cursor, false);
Dispatcher->BeginInvoke(DispatcherPriority::Render,
gcnew Action<SafeFileHandle^>(this, &WebView::SetCursor), handle);
}
CefCursorHandle定义如下:
#define CefCursorHandle cef_cursor_handle_t
...和cef_cursor_handle_t定义如下:
#define cef_cursor_handle_t HCURSOR
即。一个windef.h结构。
接口(IRenderWebBrowser)btw。定义这样的方法。
public interface class IRenderWebBrowser : IWebBrowser
{
public:
void SetCursor(CefCursorHandle cursor);
}
有一次,我认为这个问题与“const”和“non-const”问题有关,但是从例子中可以看出,没有涉及const说明符。 : - (
我在这里失踪的明显问题是什么?我浏览了this post,但它并没有真正帮助我。
我还考虑过多个/旧版本的程序集可能会挂在某处,所以我尝试碰撞程序集版本只是为了确保正确的程序集已加载 - 它就是这样。我也在装配上看了ILSpy,方法肯定在那里。但是,它的方法签名是:
public unsafe void SetCursor(HICON__* cursor)
是否与不安全的部分有关,或者它的参数(HICON __ *)无法从C#/ CLR上下文中获取? (我正在尝试从C#程序集中实例化类型。)我必须承认C ++ / CLI并不是我的专业领域,但......: - )
任何?
(如果有人想更仔细地查看详细信息,请随时在https://github.com/perlun/CefSharp/克隆/调查项目 - 这些内容存在于vs2012分支上。)
答案 0 :(得分:0)
跟进:我试图在C#中实现IRenderWebBrowser接口,只是为了试验:
public unsafe class Foo : IRenderWebBrowser
{
public void SetBuffer(int width, int height, void* buffer)
{
throw new NotImplementedException();
}
// ...and so forth.
}
现在,编译它(在启用/ unsafe标志之后)让我更深入地了解(可能)造成这种情况的原因:
1>Y:\git\ataranto.CefSharp\CefSharp.Wpf.Example\MainWindow.xaml.cs(167,31,167,38): error CS0122: 'HICON__' is inaccessible due to its protection level
1>Y:\git\ataranto.CefSharp\CefSharp.Wpf.Example\MainWindow.xaml.cs(167,21,167,30): error CS0051: Inconsistent accessibility: parameter type 'HICON__*' is less accessible than method 'CefSharp.Wpf.Example.Foo.SetCursor(HICON__*)'
1>Y:\git\ataranto.CefSharp\CefSharp.Wpf.Example\MainWindow.xaml.cs(182,45,182,52): error CS0122: 'CefRect' is inaccessible due to its protection level
1>Y:\git\ataranto.CefSharp\CefSharp.Wpf.Example\MainWindow.xaml.cs(182,21,182,44): error CS0051: Inconsistent accessibility: parameter type 'CefRect*' is less accessible than method 'CefSharp.Wpf.Example.Foo.SetPopupSizeAndPosition(CefRect*)'
如果C#/托管世界无法访问HICON__,那么类型中存在这些方法的事实很可能使CLR有点“混淆”至少说,使得类型无法实例化管理环境。在C ++ / CLI中是否有任何方法可以指定方法是公共的(实现有问题的接口),但“从CLR隐藏”(以避免愚蠢的TypeLoadExceptions等)?
答案 1 :(得分:0)
让我们希望这可以帮助别人......结果证明我的怀疑是对的,看似。因为类型是非托管(并且托管世界无法访问),所以C ++编译器将CefCursorHandle / HICON结构创建为组件中的内部 CLR结构,其中WebView是声明。这使得该方法基本上是不可调用的(具有内部参数的公共方法=&gt;无法从C#调用),并且当尝试从C#实例化类型时,CLR似乎对此进行了禁止...
将参数类型更改为IntPtr,使代码按预期工作。 “void *”也是一个选项,它有时可以更容易在C ++端使用。
(在这些情况下,这些方法不需要在C#/管理方面使用,因此使用IntPtr / void *不是问题。如果实际使用它们,正确的编组将是一个更好的主意比这更好。)