具有不同入口点的DllImport(不同项目中相同导入的不同DLL) [英] DllImport with different entry points (different DLLs for the same import in different projects)

查看:216
本文介绍了具有不同入口点的DllImport(不同项目中相同导入的不同DLL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为我的最近的问题的跟进关于.NET Compact Framework的调试,我目前正在尝试同时使用.NET Compact Framework和.NET Framework应用程序中的OpenGL ES。我使用了此包装器

As a follow-up to my recent question about .NET Compact Framework debugging, I am currently trying to use OpenGL ES from both a .NET Compact Framework and a .NET Framework application. I use this wrapper, which has been created for OpenGL ES and imports from libGLES_CM.dll.

为了简化调试,我创建了一个.NET Framework应用程序,并使用OpenGL ES和EGL重新创建了OpenGL ES和EGL的导入项目。相同的文件(只是为Desktop框架构建),为DLL名称创建了常量,因此它们将从Windows上的libGLESv2.dll和libEGL.dll以及CF上的libGLES_CM.dll导入。这些DLL来自PowerVR OpenGL ES仿真SDK(目标设备具有PowerVR SGX),并且只是围绕真实OpenGL实现的OpenGL ES包装器。问题来了:

To make debugging easier, I created a .NET Framework application, recreated the import project for OpenGL ES and EGL with the same files (just building for Desktop framework), created constants for the DLL names so they'll import from libGLESv2.dll and libEGL.dll on Windows and from libGLES_CM.dll on CF. The DLLs are from the PowerVR OpenGL ES Emulation SDK (the target device has a PowerVR SGX) and are just a OpenGL ES wrapper around the real OpenGL implementation. And here comes the problem:

在包装器库中,OpenGL函数位于两个静态类(gl和egl)中,并且具有通常的名称,但没有gl / egl前缀,因此调用它们将是 egl.GetDisplay()而不是 egl.eglGetDisplay()。它们是这样导入的:

In the wrapper library, the OpenGL functions are in two static classes (gl and egl) and have the usual name, but without the gl/egl prefix, so calling them would be egl.GetDisplay() instead of egl.eglGetDisplay(). They are imported like this:

[DllImport(DllName, EntryPoint = "eglGetDisplay")]
static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);

这在Compact Framework上很好用。在桌面项目中,会引发EntryPointNotFoundException-因为这些函数的名称类似于 _eglGetDisplay @ 4 (请注意:WMD捕获Alt-Gr + Q来获取块引用,这是德语键盘布局上的at符号。我必须粘贴此符号。)

This works fine on the Compact Framework. In the desktop project, an EntryPointNotFoundException is thrown - because the functions are named like _eglGetDisplay@4 (side note: the WMD catches Alt-Gr+Q for blockquotes, which is the at symbol on German keyboard layouts. I had to paste this one.) according to Dependency Walker.

我设法将下划线添加到了通过有条件地将字符串常量设置为空字符串或 _,然后将其与入口点名称连接起来,从而获得桌面项目的功能名称,而不是CF项目的名称。

I managed to get the underscore added to the function name for the desktop project, but not for the CF one, by conditionally setting a string constant to empty string or "_", and concatenating it and the entry point name, so it looks like this:

[DllImport(DllName, EntryPoint = FunctionPrefix + "eglGetDisplay")]

这里没问题。但是仍然找不到该函数,因为缺少了@ 4(这到底是什么?)。如果我添加@ 4,则可以使用此方法,但是由于此处所有函数的值均不同,因此我必须手动执行此操作,并且数字可能不适用于CF版本。这里是奇怪的部分:

No problem here. But the function is still not found, because the @4 (what exactly is that?) is missing. If I add the @4, this works, but since all functions have different values here, I had to do this by hand and likely the numbers wouldn't be correct for the CF version. Here comes the strange part:

如果我只是不指定入口点,而是像应该命名函数那样命名函数,则导入工作正常!现在,由于双前缀(静态类名和函数名),这很丑陋,尽管我可以为此添加一个包装器来解决这个问题。由于我不会过多地依赖这些功能(只需要一个相当简单的2D引擎),这不会有问题,但是感觉并不正确。

If I just don't specify the entry point and instead name the function like it should be named, the import works fine! Now this is ugly because of the double prefix (static class name and function name), though I could get around this by just adding a wrapper for this one. Since I won't rely heavily on these functions (need only a rather simple 2D engine), this wouldn't be a problem, but it just doesn't feel right.

为什么在指定入口点时不起作用?我该怎么做才能使其像预期的那样工作?

Why doesn't it work when specifying the entry point? What can I do to make it work like it should?

推荐答案

如果CF和桌面API的入口点不同,则需要为此工作。

If the CF and desktop APIs have different entry points you need to work with this. It means you need different DllImport's defined.

最简单的方法可能是让两个包装器类实现所有内部(.NET)名称,然后调用它们的导入,然后实例化正确的名称。在运行时取决于平台。然后通过公共接口访问API。

Easiest may be to have two wrapper classes implementing all the internal (.NET) names, which call their import, then instantiate the correct one at runtime depending on platform. Then access the APIs through the common interface.

Interface IGLImports {
   IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

static class CFRawImports {
  [DllImport(DllName, EntryPoint = "eglGetDisplay")]
  static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

static class DeskRawImports {
  [DllImport(DllName, EntryPoint = "_eglGetDisplay@4")]
  static extern IntPtr GetDisplay(EGLNativeDisplayType display_id);
}

class DesktopImports : IGLImports {
  public IntPtr GetDisplay(EGLNativeDisplayType display_id) {
    return DeskRawImports.GetDisplay(display_id);
  }
}

class CFImports : IGLImports {
  public IntPtr GetDisplay(EGLNativeDisplayType display_id) {
    return CFRawImports.GetDisplay(display_id);
  }
}

static class ImportLoader {
  public static IGLImports GetImports() {
    if (isCF) {
      return new CFImports();
    } else {
      return new DesktopImports();
    }
  }
}

class MyApp {
  private static IGLIMports gl = ImportLoader.GetImports();

  // In code use gl.GetDesktop(...)






编辑:接口和四个类应该可以通过少量代码生成来创建。包含名称DesktopImport CFImport的输入文件(如果这些名称不同,则可能添加dll名称)。成为学习VS T4模板的借口...


The interface and four classes should be creatable with a little code generation. Input file containing Name DesktopImport CFImport (maybe adding dll names if these vary). Would be an excuse to learn VS's T4 templating ...

这篇关于具有不同入口点的DllImport(不同项目中相同导入的不同DLL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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