Sie sind auf Seite 1von 5

//-------------------------------------------------------------// file: StaticSwitchyardExample.

cpp - Matlab Mex function application // This project serves as an example of two things: // (1) How to implement a 'switchyard' such that a single Mex // function can serve serveral functions. The first argument // (a string) specifies which sub function to call. // (2) How data can be preserved from call to call. // This is a C++ source file, but it there are no C++ specific things, // except the extern "C" statements. // // Web: http://www.mathworks.com/matlabcentral/newsreader/view_thread/76039 // //-------------------------------------------------------------#include <windows.h> #include <iostream.h> #include <math.h> #include <string.h> extern "C" { #include "mex.h" } // Here are the static variables that stick around from call to call. // A 'Handle' is an integer that indexes an object, In this example, // the objects are zero-terminated strings. int HandleCount; // Gets initialized in DLL #define MAX_HANDLES 100 char *StringPointer[MAX_HANDLES]; // A string pointer for each handle, NULL=unused. // // // // // // // // // // // // // // // Note: Above, I've simple allocated enough space for 100 handles (which map to string pointers). In a 'real' program, this array would be dynamically managed, so there would be no defined upper limit on the size of the data sets. Here are the three basic functions supported in this example: ObjCreate() - Creates an object with given data. Returns handle. ObjDelete() - Deletes an object ObjGet() - Retrieve the data associated with an object Note that each of these functions has the same calling structure as the core mexFunction(). Two additions function are called from DllMain(): ObjInit() - Called when DLL is loaded into memory ObjTerminate() - Called when DLL is unloaded from memory The objects in this example are strings. The handles are TBD

//-------------------------------------------------------------// ObjCreate() - Argument must be a string. Allocates memory for // it a returns the associated handle. //-------------------------------------------------------------void ObjCreate( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { int h, NumEl; int rc = -1; // Return code; default = -1 = error // Make sure the argument is a string. if (nrhs < 1 || !mxIsChar(prhs[0])) mexErrMsgTxt("'create' requires a string");

NumEl = mxGetNumberOfElements(prhs[0]); // Number of characters // Look for an empty handle. In none left, return -1. for (h=0; h<MAX_HANDLES; h++) { if (StringPointer[h] == NULL) { // Caveat: If you decide to use mxMalloc() instead of // malloc(), you must use mexMakeMemoryPersistent(). StringPointer[h] = (char *)malloc(NumEl+1); mxGetString(prhs[0], StringPointer[h], NumEl+1); rc = h; // This the handle now. break; } } plhs[0] = mxCreateScalarDouble((double)rc); // Error code } // end ObjCreate() //-------------------------------------------------------------// ObjDelete() - Remove data associated a handle. // Argument must be a handle (integral double). //-------------------------------------------------------------void ObjDelete( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { int h; if (nrhs < 1 || !mxIsDouble(prhs[0]) || mxGetNumberOfElements(prhs[0]) != 1) mexErrMsgTxt("'delete' requires a handle"); h = (int)*mxGetPr(prhs[0]); if (h<0 || h>= MAX_HANDLES || StringPointer[h] == NULL) mexErrMsgTxt("invalid handle"); // If mxMalloc() was used, the mxFree() must be used here. free(StringPointer[h]); // Return associated string StringPointer[h] = NULL; // Make handle invalid. } // end ObjDelete() //-------------------------------------------------------------// ObjGet() - Return the data associated a handle. // Argument must be a handle (integral double). //-------------------------------------------------------------void ObjGet( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { int h; if (nrhs < 1 || !mxIsDouble(prhs[0]) || mxGetNumberOfElements(prhs[0]) != 1) mexErrMsgTxt("'get' requires a handle"); h = (int)*mxGetPr(prhs[0]); if (h<0 || h>= MAX_HANDLES || StringPointer[h] == NULL) mexErrMsgTxt("invalid handle"); plhs[0] = mxCreateString(StringPointer[h]); // Return associated string } // end ObjGet()

//-------------------------------------------------------------// ObjInit() - Called when DLL is loaded (see DllMain()), and // initializes global data. //-------------------------------------------------------------void ObjInit(void) { int h; HandleCount = 0; for (h=0; h<MAX_HANDLES; h++) { StringPointer[h] = NULL; } } // end ObjInit() //-------------------------------------------------------------// ObjTerminate() - Called when DLL is unloaded (see DllMain()), and // cleans up malloc'ed data. //-------------------------------------------------------------void ObjTerminate(void) { int h; for (h=0; h<MAX_HANDLES; h++) { // If mxMalloc() was used, the mxFree() must be used here. if (StringPointer[h] != NULL) free(StringPointer[h]); } } // end ObjTerminate() extern "C" { // The switchyard: // First, a table that maps command strings to "mex" functions typedef void (* MEXFUNCTION)( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ); struct _cmd_data { char *pCmd; void (*pFunction)( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ); } CmdTable[] = { {"create" , ObjCreate}, {"delete" , ObjDelete}, {"get" , ObjGet} }; } //-------------------------------------------------------------// function: StaticSwitchyardExample - Entry point from Matlab environment (via // mexFucntion(), below) // INPUTS: // nlhs - number of left hand side arguments (outputs) // plhs[] - pointer to table where created matrix pointers are // to be placed // nrhs - number of right hand side arguments (inputs) // prhs[] - pointer to table of input matrices //-------------------------------------------------------------void StaticSwitchyardExample( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {

// TODO: Add your application code here } // end StaticSwitchyardExample() extern "C" { //-------------------------------------------------------------// mexFunction - Entry point from Matlab. Evaluate the first // argument (must be a string) to decide which subfuntion to // call. //-------------------------------------------------------------void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { char StrBuffer[65]; static char ErrBuffer[512]; int h; if (nrhs < 1) { strcpy(ErrBuffer, "Missing command string. Expecting one of:"); for (h=0; h<sizeof(CmdTable)/sizeof(CmdTable[0]); h++) { sprintf(StrBuffer, "\n %s", CmdTable[h].pCmd); strcat(ErrBuffer, StrBuffer); } mexErrMsgTxt(ErrBuffer); } if (!mxIsChar(prhs[0])) mexErrMsgTxt("First argument must be a command string"); if (mxGetString(prhs[0], StrBuffer, sizeof(StrBuffer)-1)) mexErrMsgTxt("Unable to read first argument: commnad string"); for (h=0; h<sizeof(CmdTable)/sizeof(CmdTable[0]); h++) { if (!strcmp(CmdTable[h].pCmd, StrBuffer)) { CmdTable[h].pFunction(nlhs, plhs, nrhs-1, prhs+1); return; } } mexErrMsgTxt("Invalid command"); nlhs = nlhs; // avoid compiler warning plhs = plhs; // avoid compiler warning } // end mexFunction } //-------------------------------------------------------------// DllMain() - This is called when DLL is loaded. Perform // initialization. Global variable initialization and // destruction should happen here. Requires <windows.h>. // FYI: // typedef int BOOL; // #define WINAPI __stdcall // typedef void *HINSTANCE; // typedef unsigned long DWORD;

// typedef void far *LPVOID; // #define DLL_PROCESS_ATTACH 1 // #define DLL_THREAD_ATTACH 2 // #define DLL_THREAD_DETACH 3 // #define DLL_PROCESS_DETACH 0 //-------------------------------------------------------------BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpvReserved // reserved ) { switch(fdwReason) { case DLL_PROCESS_ATTACH: printf("DLL_PROCESS_ATTACH: hinstDLL=0x%x\n", hinstDLL); // informational message ObjInit(); // Perform initialiation stuff here. break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: printf("DLL_PROCESS_DETTACH: hinstDLL=0x%x\n", hinstDLL); // informational message ObjTerminate(); // Perform termination stuff here. break; default: break; } hinstDLL = hinstDLL; // Prevent compiler warning lpvReserved = lpvReserved; // Prevent compiler warning return TRUE; } // end DllMain()

Das könnte Ihnen auch gefallen