Sign in to follow this  
Followers 0
JRowe

Plugins question, passing pointer to dllStruct?

5 posts in this topic

I'm working on a poker hand evaluator plugin, and I've got it pretty much completed, but I'm running into a small issue.

I have the AnalyzeHand function completely built; it takes 7 numbers (indicative of a card, 1-52), then ranks and categorizes the hand based on the algorithm devised on this thread. It works just fine, but at one point, the plugin has to load and close a HandRanks.dat file, which is 123 MB.

Actually, it just looks up the position on the table, then I use AutoIt bitAnd and bitShift to get the rank and category values, because passing one value back to AutoIt is just easier.

Is there a way I can load the file in the AutoIt script, and access it via the plugin? Loading adds anywhere from 2-10 seconds to the execution time of the function, whereas the actual ranking takes around 200-300 ms. Caching sometimes speeds up the entire process, but it's undependable in this context.

Here's the code within the plugin. Memory is allocated prior to this snippet, and then the file is loaded, the HR array built, and then the file is closed.

memset(HR, 0, sizeof(HR));
    FILE * fin = fopen("HandRanks.dat", "rb");
    if (!fin)
        return false;
    size_t bytesread = fread(HR, sizeof(HR), 1, fin);
    fclose(fin);

Ideally I'd like to use AutoIt to load the file, then create the array in memory, and pass a pointer to the plugin function whenever it's called, so that all the plugin has to do is traverse the array.

What I'm seeing in the code above is that fread allocates "fin" (the HandRanks.dat file) to the array HR, at pointer HR, in one big chunk, of the size 32487834.

$HandRanksData = FileOpen ( "HandRanks.dat", 0 )
$HandRanksStruct = DllStructCreate("int[32487834]")
DllStructSetData($HandRanksStruct, 1, $HandRanksData)
$PointerToHandRanksStruct = DllStructGetPtr($HandRanksStruct)
;Set the card values, $card1 through $card7 (after I get this worked out I'll hit up 5 and 6 card hands.)
AnalyzeHand($card1, $card2, $card3, $card4, $card5, $card6, $card7, $PointerToHandRanksStruct)
;Do whatever else you're gonna do after the lookup
;Eventually deallocate the memory and clean up after yourself.

So hopefully, that would allocate the memory, write HandRanks.dat to that chunk of memory, and then all I'd have to do would be to pass $PointerToHandRanksStruct to my plugin function, so it can simply access the data via the pointer, instead of reloading the entire structure every time the function is called.

Is this the right way to do it? I'm still kind of struggling with the pointers and memory structures, but it seems like it would work.

Here's the source for the entire plugin (you'll need the SDK, this is just a hacked up example.cpp). Could someone point out how I'd use the pointer if it were passed in, within the lookUpHand function?

Thanks!

CODE
#include <stdio.h>

#include <windows.h>

#include "AU3_Plugin_SDK\au3plugin.h"

/****************************************************************************

* Function List

*

* This is where you define the functions available to AutoIt. Including

* the function name (Must be the same case as your exported DLL name), the

* minimum and maximum number of parameters that the function takes.

*

****************************************************************************/

/* "FunctionName", min_params, max_params */

AU3_PLUGIN_FUNC g_AU3_Funcs[] =

{

{"AnalyzeHand", 7, 7}

};

/****************************************************************************

* AU3_GetPluginDetails()

*

* This function is called by AutoIt when the plugin dll is first loaded to

* query the plugin about what functions it supports. DO NOT MODIFY.

*

****************************************************************************/

AU3_PLUGINAPI int AU3_GetPluginDetails(int *n_AU3_NumFuncs, AU3_PLUGIN_FUNC **p_AU3_Func)

{

/* Pass back the number of functions that this DLL supports */

*n_AU3_NumFuncs = sizeof(g_AU3_Funcs)/sizeof(AU3_PLUGIN_FUNC);

/* Pack back the address of the global function table */

*p_AU3_Func = g_AU3_Funcs;

return AU3_PLUGIN_OK;

}

/****************************************************************************

* DllMain()

*

* This function is called when the DLL is loaded and unloaded. Do not

* modify it unless you understand what it does...

*

****************************************************************************/

BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:

break;

}

return TRUE;

}

/****************************************************************************

*AnalyzeHand

*

****************************************************************************/

int HR[32487834];

int LookupHand(int* pCards)

{

int p = HR[53 + *pCards++];

p = HR[p + *pCards++];

p = HR[p + *pCards++];

p = HR[p + *pCards++];

p = HR[p + *pCards++];

p = HR[p + *pCards++];

return HR[p + *pCards++];

}

AU3_PLUGIN_DEFINE(AnalyzeHand)

{

AU3_PLUGIN_VAR *pMyResult;

int card1, card2, card3, card4, card5, card6, card7, rawEval;

/* Allocate the return variable */

pMyResult = AU3_AllocVar();

/* Two parameters were numbers, get the values */

card1 = AU3_GetInt32(&p_AU3_Params[0]);

card2 = AU3_GetInt32(&p_AU3_Params[1]);

card3 = AU3_GetInt32(&p_AU3_Params[2]);

card4 = AU3_GetInt32(&p_AU3_Params[3]);

card5 = AU3_GetInt32(&p_AU3_Params[4]);

card6 = AU3_GetInt32(&p_AU3_Params[5]);

card7 = AU3_GetInt32(&p_AU3_Params[6]);

//rawEval = card1 + card2 + card3 + card4 + card5 + card6 + card7;

int cards[] = {card1, card2, card3, card4, card5, card6, card7};

memset(HR, 0, sizeof(HR));

FILE * fin = fopen("HandRanks.dat", "rb");

if (!fin)

return false;

size_t bytesread = fread(HR, sizeof(HR), 1, fin); // get the HandRank Array

fclose(fin);

rawEval = LookupHand(cards);

AU3_SetInt32(pMyResult, rawEval);

/* Pass back the result, error code and extended code.

* Note: AutoIt is responsible for freeing the memory used in p_AU3_Result

*/

*p_AU3_Result = pMyResult;

*n_AU3_ErrorCode = 0;

*n_AU3_ExtCode = 0;

return AU3_PLUGIN_OK;

}

Btw, if there's any interest, I'll link to the source needed to generate the HandRanks.dat, without which this isn't much use to anyone.

Share this post


Link to post
Share on other sites



Just create two additional functions. The first should load the file and return a handle to the memory. The second function would take a handle and free the memory. The analyze function should be modified to work on the memory handle.

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

The DLL is loaded when you call PluginOpen() and unloaded when you call PluginClose().

Share this post


Link to post
Share on other sites

Much thanks valik. I revised what I had and now I can analyze 100 random 7 card hands in less than half a second. I think I like this. :P

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0