Matlab crashes runing Multi Thread s-function with openGL
    8 views (last 30 days)
  
       Show older comments
    
Hi! I try to write a simple s-function with openGL/freeglut. I compile it within Visual Studio ( how to do it ). When i run my s-function in Simulink it works only the first time. The second attempt of running the model results in Matlab crash, but the matlab process steel exist in a memory.
May be there is a mistake with memory or thread manipulation? I find out that Matlab crashes at glutInit function
Will be very glad if somebody can help me because i have found almost no information about s-function used with multithreading or openGL.
Here is the code:
    #define S_FUNCTION_NAME  my_sf
    #define S_FUNCTION_LEVEL 2
    #include <simstruc.h>
    #include <freeglut.h>
    #include <Math.h>     
    #include <windows.h>
    #include <process.h>
    #include <stdio.h>
    struct data_st {
      unsigned ThreadId;
      HANDLE hThread, hEvent;
    };
    void display() {
      glClear(GL_COLOR_BUFFER_BIT);   // Clear the color buffer with current clearing color
      // Define shapes enclosed within a pair of glBegin and glEnd
      glBegin(GL_QUADS);              // Each set of 4 vertices form a quad
      glColor3f(1.0f, 0.0f, 0.0f); // Red
      glVertex2f(-0.8f, 0.1f);     // Define vertices in counter-clockwise (CCW) order
      glVertex2f(-0.2f, 0.1f);     //  so that the normal (front-face) is facing you
      glVertex2f(-0.2f, 0.7f);
      glVertex2f(-0.8f, 0.7f);
      glColor3f(0.0f, 1.0f, 0.0f); // Green
      glVertex2f(-0.7f, -0.6f);
      glVertex2f(-0.1f, -0.6f);
      glVertex2f(-0.1f, 0.0f);
      glVertex2f(-0.7f, 0.0f);
      glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
      glVertex2f(-0.9f, -0.7f);
      glColor3f(1.0f, 1.0f, 1.0f); // White
      glVertex2f(-0.5f, -0.7f);
      glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
      glVertex2f(-0.5f, -0.3f);
      glColor3f(1.0f, 1.0f, 1.0f); // White
      glVertex2f(-0.9f, -0.3f);
      glEnd();
      glBegin(GL_TRIANGLES);          // Each set of 3 vertices form a triangle
      glColor3f(0.0f, 0.0f, 1.0f); // Blue
      glVertex2f(0.1f, -0.6f);
      glVertex2f(0.7f, -0.6f);
      glVertex2f(0.4f, -0.1f);
      glColor3f(1.0f, 0.0f, 0.0f); // Red
      glVertex2f(0.3f, -0.4f);
      glColor3f(0.0f, 1.0f, 0.0f); // Green
      glVertex2f(0.9f, -0.4f);
      glColor3f(0.0f, 0.0f, 1.0f); // Blue
      glVertex2f(0.6f, -0.9f);
      glEnd();
      glBegin(GL_POLYGON);            // These vertices form a closed polygon
      glColor3f(1.0f, 1.0f, 0.0f); // Yellow
      glVertex2f(0.4f, 0.2f);
      glVertex2f(0.6f, 0.2f);
      glVertex2f(0.7f, 0.4f);
      glVertex2f(0.6f, 0.6f);
      glVertex2f(0.4f, 0.6f);
      glVertex2f(0.3f, 0.4f);
      glEnd();
      glFlush();  // Render now
    }
    void do_nothing(void) {
      return;
    }
    unsigned __stdcall plot(struct data_st* data) {
      char *argv[1];
      int argc = 1;
      argv[0] = strdup("Myappname");
      glutInit(&argc, argv);          // Initialize GLUT
      glutCreateWindow("Vertex, Primitive & Color");  // Create window with the given title
      glutInitWindowSize(320, 320);   // Set the window's initial width & height
      glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
      glutDisplayFunc(do_nothing);       // Register callback handler for window re-paint event
      glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
      while (WaitForSingleObject(data->hEvent, 0) != WAIT_OBJECT_0) {
        display();
        glutMainLoopEvent();
      }
      //glutDestroyWindow( glutGetWindow() );
      return(0);
    }
    /* Function: mdlInitializeSizes ===============================================
     * Abstract:
     *   Setup sizes of the various vectors.
     */
    static void mdlInitializeSizes(SimStruct *S)
    {
        ssSetNumSFcnParams(S, 0);
        if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
            return; /* Parameter mismatch will be reported by Simulink */
        }
        if (!ssSetNumInputPorts(S, 1)) return;
        ssSetInputPortWidth(S, 0, 1);
        ssSetInputPortDirectFeedThrough(S, 0, 1);
        if (!ssSetNumOutputPorts(S,1)) return;
        ssSetOutputPortWidth(S, 0, 1);
        ssSetNumSampleTimes(S, 1);
        /* specify the sim state compliance to be same as a built-in block */
        ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
      ssSetNumDWork(S, 1);
      ssSetDWorkWidth(S, 0, 1);
      ssSetDWorkDataType(S, 0, SS_POINTER);
        ssSetOptions(S,
                     SS_OPTION_WORKS_WITH_CODE_REUSE |
                     SS_OPTION_EXCEPTION_FREE_CODE |
                     SS_OPTION_USE_TLC_WITH_ACCELERATOR);
    }
    #define MDL_START
    void mdlStart(SimStruct *S)
    {
      void **Ptrs = (void**)ssGetDWork(S, 0);
      struct data_st* data;
      data = (void*)malloc(sizeof(struct data_st));
      Ptrs[0] = data;
      data -> hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
      data -> hThread = (HANDLE)_beginthreadex(NULL, 0, plot, data, 0, &(data->ThreadId));
      if (data->hThread == 0)
        return;
    }
    /* Function: mdlInitializeSampleTimes =========================================
     * Abstract:
     *    Specifiy that we inherit our sample time from the driving block.
     */
    static void mdlInitializeSampleTimes(SimStruct *S)
    {
        ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
        ssSetOffsetTime(S, 0, 0.0);
        ssSetModelReferenceSampleTimeDefaultInheritance(S); 
    }
    /* Function: mdlOutputs =======================================================
     * Abstract:
     *    y = 2*u
     */
    static void mdlOutputs(SimStruct *S, int_T tid)
    {
        InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
        real_T            *y    = ssGetOutputPortRealSignal(S,0);
        *y = 2.0 *(*uPtrs[0]); 
    }
    /* Function: mdlTerminate =====================================================
     * Abstract:
     *    No termination needed, but we are required to have this routine.
     */
    static void mdlTerminate(SimStruct *S)
    {
      void **Ptrs = (void**)ssGetDWork(S, 0);
      struct data_st* data;
      data = Ptrs[0];
      SetEvent(data->hEvent); // init event for thread stop
      WaitForSingleObject(data->hThread, INFINITE); // wait thread to be finised
      CloseHandle(data->hEvent);
      CloseHandle(data->hThread);
      free(data);
    }
    #ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-file? */
    #include "simulink.c"      /* MEX-file interface mechanism */
    #else
    #include "cg_sfun.h"       /* Code generation registration function */
    #endif
0 Comments
Accepted Answer
More Answers (0)
See Also
Categories
				Find more on Simulink Coder in Help Center and File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!