C# 4.0 PInvoke 问题(ATI AGS 库)

发布于 2024-09-24 20:32:24 字数 2765 浏览 3 评论 0原文

我下载了 ATI AGS(ATI GPU 服务)库,并尝试使用此 API 从 C# 检索一些基本驱动程序信息。 ATI AGS 库可从此处下载:

http://developer.amd。 com/gpu/ags/Pages/default.aspx

我编写了一些 C# 代码来使用 AGS API 从 GPU 提取驱动程序信息,但我在调用非托管方法时遇到了一些问题。我尝试了 DllImportAttribute 参数的各种不同排列,但无济于事。我收到 MarshalDirectiveException 或 pInvokeStackImbalance。

我很确定这都是由于不正确的 P/Invoke 签名造成的,但我已经用尽了对此 API 的了解。

顺便说一句,您会看到我正在使用 32 位 DLL,而且我似乎在这方面做得更进一步,但是当我使用 64 位 DLL 时,我得到了 BadImageFormatException。

这是我正在使用的代码:

    [DllImport(
            "atiags.dll"
            , PreserveSig=false
            , ExactSpelling=true
            , ThrowOnUnmappableChar=true
            , CharSet=CharSet.Unicode
            , EntryPoint="agsDriverGetVersionInfo"
    )]
    public static extern void agsDriverGetVersionInfo(
        [MarshalAs(UnmanagedType.Struct)]
        out agsDriverVersionInfoStruct DriverInfo
    );

    public static agsDriverVersionInfoStruct GetAgsDriverVersion()
    {
       agsDriverVersionInfoStruct DriverInfo = new agsDriverVersionInfoStruct();
       agsDriverGetVersionInfo(out DriverInfo);
    }

    public struct agsDriverVersionInfoStruct
    {
        [MarshalAs(UnmanagedType.LPTStr)]
        public string strDriverVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string strCatalystVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string strCatalystWebLink;
    }

有什么想法吗?

编辑:以下是 ati_ags.h 中 ATIAGSDriverGetVersionInfo() 函数的定义。根据 ATI AGS 文档(下载中包含的 PDF),它说要定义 _ATI_AGS_USE_DLL,因此我在 C# 类代码文件的顶部添加了这一行:

文档引用

确定 AGS 功能是否将通过 dll 或静态库访问。如果选择 dll 选项,请确保在项目属性中定义 _ATI_AGS_USE_DLL。如果选择 static lib 选项,则无需定义特殊标记。

__inline AGSReturnCode ATIAGSDriverGetVersionInfo( AGSDriverVersionInfoStruct *lpDriverVersionInfo )
{
AGSReturnCode iReturnValue = AGS_SUCCESS;

// Validate params
if ( NULL == lpDriverVersionInfo )
{
    return AGS_FAILURE;
}

#ifdef _ATI_AGS_USE_DLL
// Load the lib
HINSTANCE lib = NULL;
lib = LoadLibrary(TEXT("atiags.dll"));
if (NULL == lib)
{
    lib = LoadLibrary(TEXT("atiags64.dll"));
    if (NULL == lib)
    {
        return AGS_FAILURE;     
    }
}

// Get the function pointer
AGSDRIVERGETVERSIONINFO agsDriverGetVersionInfo = NULL;
agsDriverGetVersionInfo = (AGSDRIVERGETVERSIONINFO)GetProcAddress(lib, "agsDriverGetVersionInfo");
if (NULL == agsDriverGetVersionInfo)
{
    FreeLibrary(lib);
    return AGS_FAILURE;
}
#endif // _ATI_AGS_USE_DLL

// Get the number of GPUs
iReturnValue = agsDriverGetVersionInfo( lpDriverVersionInfo );

#ifdef _ATI_AGS_USE_DLL
// Free the lib
FreeLibrary(lib);
#endif // _ATI_AGS_USE_DLL

return iReturnValue;
}

I downloaded the ATI AGS (ATI GPU Services) Libary, and am attempting to retrieve some basic driver information using this API, from C#. The ATI AGS library is available for download from here:

http://developer.amd.com/gpu/ags/Pages/default.aspx

I wrote a little bit of C# code to pull driver information from the GPU using the AGS API, but I'm having some trouble calling the unmanaged method. I've tried all sorts of different permutations of DllImportAttribute parameters, to no avail. I'm getting either a MarshalDirectiveException or a pInvokeStackImbalance.

I'm pretty sure that this is all due to an incorrect P/Invoke signature, but I have exhausted my knowledge of this API.

By the way, as an aside, you'll see that I'm using the 32-bit DLL, and I seem to be getting farther with it, but when I use the 64-bit DLL, I get a BadImageFormatException.

Here is the code that I'm using:

    [DllImport(
            "atiags.dll"
            , PreserveSig=false
            , ExactSpelling=true
            , ThrowOnUnmappableChar=true
            , CharSet=CharSet.Unicode
            , EntryPoint="agsDriverGetVersionInfo"
    )]
    public static extern void agsDriverGetVersionInfo(
        [MarshalAs(UnmanagedType.Struct)]
        out agsDriverVersionInfoStruct DriverInfo
    );

    public static agsDriverVersionInfoStruct GetAgsDriverVersion()
    {
       agsDriverVersionInfoStruct DriverInfo = new agsDriverVersionInfoStruct();
       agsDriverGetVersionInfo(out DriverInfo);
    }

    public struct agsDriverVersionInfoStruct
    {
        [MarshalAs(UnmanagedType.LPTStr)]
        public string strDriverVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string strCatalystVersion;
        [MarshalAs(UnmanagedType.LPStr)]
        public string strCatalystWebLink;
    }

Any ideas?

Edit: Here is the definition of the ATIAGSDriverGetVersionInfo() function in ati_ags.h. According to the ATI AGS documentation (a PDF included in the download), it says to define _ATI_AGS_USE_DLL, so I added this line at the top of my C# class code file:

Documentation Quote

Determine if AGS functionality will be accessed through a dll or static lib. If the dll option is chosen, make sure to define _ATI_AGS_USE_DLL in your project properties. If the static lib option is chosen, no special token needs to be defined.

__inline AGSReturnCode ATIAGSDriverGetVersionInfo( AGSDriverVersionInfoStruct *lpDriverVersionInfo )
{
AGSReturnCode iReturnValue = AGS_SUCCESS;

// Validate params
if ( NULL == lpDriverVersionInfo )
{
    return AGS_FAILURE;
}

#ifdef _ATI_AGS_USE_DLL
// Load the lib
HINSTANCE lib = NULL;
lib = LoadLibrary(TEXT("atiags.dll"));
if (NULL == lib)
{
    lib = LoadLibrary(TEXT("atiags64.dll"));
    if (NULL == lib)
    {
        return AGS_FAILURE;     
    }
}

// Get the function pointer
AGSDRIVERGETVERSIONINFO agsDriverGetVersionInfo = NULL;
agsDriverGetVersionInfo = (AGSDRIVERGETVERSIONINFO)GetProcAddress(lib, "agsDriverGetVersionInfo");
if (NULL == agsDriverGetVersionInfo)
{
    FreeLibrary(lib);
    return AGS_FAILURE;
}
#endif // _ATI_AGS_USE_DLL

// Get the number of GPUs
iReturnValue = agsDriverGetVersionInfo( lpDriverVersionInfo );

#ifdef _ATI_AGS_USE_DLL
// Free the lib
FreeLibrary(lib);
#endif // _ATI_AGS_USE_DLL

return iReturnValue;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乱世争霸 2024-10-01 20:32:24

这对我有用......

public enum AGSReturnCode
{
    AGS_ERROR_MISSING_DLL = -2,
    AGS_ERROR_LEGACY_DRIVER = -1,
    AGS_FAILURE = 0,
    AGS_SUCCESS = 1
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct AGSDriverVersionInfoStruct
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strDriverVersion;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strCatalystVersion;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strCatalystWebLink;
}

public static class AGSharp
{
    [DllImport("atiags.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "agsDriverGetVersionInfo")]
    public static extern AGSReturnCode agsDriverGetVersionInfo(out AGSDriverVersionInfoStruct driver_info);
}

似乎错误的调用约定造成了麻烦(就像理查德已经指出的那样)

This does the trick for me...

public enum AGSReturnCode
{
    AGS_ERROR_MISSING_DLL = -2,
    AGS_ERROR_LEGACY_DRIVER = -1,
    AGS_FAILURE = 0,
    AGS_SUCCESS = 1
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct AGSDriverVersionInfoStruct
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strDriverVersion;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strCatalystVersion;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string strCatalystWebLink;
}

public static class AGSharp
{
    [DllImport("atiags.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "agsDriverGetVersionInfo")]
    public static extern AGSReturnCode agsDriverGetVersionInfo(out AGSDriverVersionInfoStruct driver_info);
}

... seems like the wrong calling convention was causing troubles (like Richard pointed out already)

怎会甘心 2024-10-01 20:32:24

ati_ags.h 中,AGSDriverVersionInfoStruct 结构声明如下:

typedef struct _AGSDriverVersionInfoStruct {
  char strDriverVersion[256];
  char strCatalystVersion[256];
  char strCatalystWebLink[256];
} AGSDriverVersionInfoStruct;

以下是我在 C# 中声明等效项的方式:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct AGSDriverVersionInfoStruct {
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strDriverVersion;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strCatalystVersion;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strCatalystWebLink;
}

In ati_ags.h the AGSDriverVersionInfoStruct struct is declared as follows:

typedef struct _AGSDriverVersionInfoStruct {
  char strDriverVersion[256];
  char strCatalystVersion[256];
  char strCatalystWebLink[256];
} AGSDriverVersionInfoStruct;

Here's how I would declare the equivalent in C#:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct AGSDriverVersionInfoStruct {
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strDriverVersion;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strCatalystVersion;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  public string strCatalystWebLink;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文