flanker
flanker

Reputation: 101

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

I'm trying to get the FPS data from "Fraps". There is a project called LCDHost on github which has done this. Apparently it's done by hooking to "fraps.dll"

I need to port this code to a C# project i'm working on. Problem is I'm not good at C++ and haven't got any experience in accessing unmanaged dlls from C#.

If someone can give me pointers on how to convert this code to C#, I'd appreciate that.

#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;
}

The line that really stumped me is this one

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

I don't know what's the equivalent of it in C#

The full code can be found here

Upvotes: 1

Views: 630

Answers (2)

flanker
flanker

Reputation: 101

Figured it out. Here is how I managed.

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;
        }


    }
}

And at the top you need to

using System.Runtime.InteropServices;

Using unmanaged DLLs in C# code is far more complicated then I initially thought. One thing I don't understand, how do we figure out the stuct's structure in the first place?

Upvotes: 0

Nikolai Arsenov
Nikolai Arsenov

Reputation: 464

Use DllImport Attribute and it will call an unmanaged dlls. Just find the necessary C library call an appropriate function from it. Very useful example is there: https://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx

Upvotes: 3

Related Questions