如何将DLL访问代码从C++移植到C#

How to port a DLL access code from C++ to C#

本文关键字:C++ 代码 DLL 访问      更新时间:2023-10-16

我正试图从"Fraps"中获取FPS数据。github上有一个名为LCDHost的项目已经做到了这一点。显然,这是通过挂接"fraps.dll"完成的

我需要将这些代码移植到我正在处理的C#项目中。问题是我不擅长C++,也没有从C#访问非托管dll的任何经验。

如果有人能告诉我如何将这些代码转换为C#,我将不胜感激。

#include <stdio.h>
#include <windows.h>
#include "LH_Text.h"
struct FRAPS_SHARED_DATA {
   DWORD sizeOfStruct;
   DWORD currentFPS;
   DWORD totalFrames;
   DWORD timeOfLastFrame;
   char gameName[32];
};
FRAPS_SHARED_DATA *(WINAPI *FrapsSharedData) ();    
int notify(int n,void* p)
{
    if( !n || n&LH_NOTE_SECOND )
    {
        HMODULE frapsDLL;
        FRAPS_SHARED_DATA *fsd;
        frapsDLL = GetModuleHandleA("FRAPS32.DLL");
        if (!frapsDLL) {
            if( setText("N/A") ) callback(lh_cb_render,NULL);
        } else {
            FrapsSharedData = (typeof(FrapsSharedData)) GetProcAddress(frapsDLL, "FrapsSharedData");
            if (!FrapsSharedData) {
                if( setText("Needs Fraps 1.9C or later!") ) callback(lh_cb_render,NULL);
            } else {
                if( setText( "Fraps is running & is the right version." ) ) callback(lh_cb_render,NULL);
                fsd = FrapsSharedData();
                if( setText(QString::number(fsd->currentFPS) ) ) callback(lh_cb_render,NULL);
            }
        }
    }
    return LH_Text::notify(n,p) | LH_NOTE_SECOND;
}

真正让我困惑的是这条

FrapsSharedData = (typeof(FrapsSharedData)) GetProcAddress(frapsDLL, "FrapsSharedData");

我不知道它在C#中的等价物是什么

完整的代码可以在这里找到

使用DllImport属性,它将调用非托管dll。只需从中找到必要的C库调用一个适当的函数。非常有用的例子如下:https://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx

想明白了。以下是我是如何做到的。

class fraps
{
    [StructLayout(LayoutKind.Sequential)]
    public struct sFraps
    {
        public int SizeOfStruct;
        public int CurrentFPS;
        public uint TotalFrames;
        public uint TimeOfLastFrame;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
        public char[] GameName;
    };
    [DllImport("FRAPS32.dll")]
    public static extern IntPtr FrapsSharedData();
    public int fpsGet() {
        try
        {
            sFraps fps = (sFraps)Marshal.PtrToStructure(FrapsSharedData(), typeof(sFraps));
            return fps.CurrentFPS;
        }
        catch
        {
            return -1;
        }

    }
}

在顶部,您需要

using System.Runtime.InteropServices;

在C#代码中使用非托管DLL比我最初想象的要复杂得多。有一件事我不明白,我们一开始是如何弄清楚灰泥的结构的?