Missing Information in UDF Example in 6.4 Documentation

40 views
Skip to first unread message

Jimmy Allison

unread,
Aug 4, 2023, 12:27:48 PM8/4/23
to CLIPSESG
Hello!

I am attempting to run the EulersNumber example and I receive the below error:

userfunctions.c: In function ‘UserFunctions’:                                                                                                                                                                                                                                                                         

userfunctions.c:69:33: error: EulersNumber’ undeclared (first use in this function)                                                                                                                                                                                                                                  

   69 |     AddUDF(env,"e","d",0,0,NULL,EulersNumber,"EulersNumber",NULL);                                                                                                                                                                                                                                            

      |                                 ^~~~~~~~~~~~                                                                                                                                                                                                                                                                  

userfunctions.c:69:33: note: each undeclared identifier is reported only once for each function it appears in                                                                                                                                                                                                         

make: *** [makefile:91: userfunctions.o] Error 1                                                               


I followed the example in the documentation but there appears to be something more the compiler is expecting. (Perhaps something an experienced programmer would understand and that the example assumes the reader would know.)

No changes within the CLIPS code base were made other than inserting the AddUDF in userfunctions.c:

void UserFunctions(

  Environment *env)

{


  {

    AddUDF(env,"e","d",0,0,NULL,EulersNumber,"EulersNumber",NULL);

  }


#if MAC_XCD

#pragma unused(env)

#endif

}


and the function itself, EulersNumber.c:

#include <math.h>

void EulersNumber(

                  Environment *env,

                  UDFContext *udfc,

                  UDFValue *out)

{

  out->floatValue = CreateFloat(env,exp(1.0));

}


That I am uninitiated to the world of C coding is brought home to me by the third paragraph of "Section 8: User Defined Functions"  which I do not understand and I suspect is the root of my problem:

"This section describes the protocols for registering UDFs, passing arguments to them, and returning values from them. Prototypes for the functions listed in this section can be included by using the clips.h header file."

Is it something I should do with clips.h?

Thank you




                                                                                                               |

CLIPS Support

unread,
Aug 4, 2023, 1:30:02 PM8/4/23
to CLIPSESG
You have to declare explicitly prototypes for functions in C if other functions are going to reference them.  The prototype for the EulersNumber function is:

void EulersNumber(Environment *,UDFContext *,UDFValue *);


The common practice is to create a file named EulersNumber.h, place the prototype in that file, and then place a #include "EulersNumber.h" within userfunctions.c. 


Jimmy Allison

unread,
Aug 5, 2023, 9:08:48 AM8/5/23
to clip...@googlegroups.com
Gary,

Thank you for the speedy response. Unfortunately, I am still having problems.

I did as you directed, yet I am getting the following link error:

gcc -o clips main.o -L. -lclips -lm                                                                                                                                                                                                                                                                                   

/usr/bin/ld: ./libclips.a(userfunctions.o): in function `UserFunctions':                                                                                                                                                                                                                                              

userfunctions.c:(.text+0x2a): undefined reference to `EulersNumber'                                                                                                                                                                                                                                                   

collect2: error: ld returned 1 exit status                                                                                                                                                                                                                                                                            

make: *** [makefile:94: clips] Error 1     


Here is my EulersNumber.c

#include <math.h>


void EulersNumber(

                  Environment *env,

                  UDFContext *udfc,

                  UDFValue *out)

{

  out->floatValue = CreateFloat(env,exp(1.0));

}


Here is my EulersNumber.h

void EulersNumber(Environment *,UDFContext *,UDFValue *);


Here is my userfunctions.c

#include "clips.h"


#include "EulersNumber.h"


void UserFunctions(Environment *);


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

/* UserFunctions: Informs the expert system environment  */

/*   of any user defined functions. In the default case, */

/*   there are no user defined functions. To define      */

/*   functions, either this function must be replaced by */

/*   a function with the same name within this file, or  */

/*   this function can be deleted from this file and     */

/*   included in another file.                           */

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

void UserFunctions(

  Environment *env)

{


  {

    AddUDF(env,"e","d",0,0,NULL,EulersNumber,"EulersNumber",NULL);

  }


#if MAC_XCD

#pragma unused(env)

#endif


Thank you in advance for any insights into what I might be missing.

Jim Allison









--
You received this message because you are subscribed to the Google Groups "CLIPSESG" group.
To post to this group, send email to CLIP...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/CLIPSESG?hl=en
 
--> IF YOU NO LONGER WANT TO RECEIVE EMAIL <--
Visit this group at http://groups.google.com/group/CLIPSESG?hl=en
Click on "Edit my membership" link.
Select the "No Email" radio button.
Click the "Save these settings" button.

--> IF YOU WANT TO UNSUBSCRIBE <--
Visit this group at http://groups.google.com/group/CLIPSESG?hl=en
Sign in
Click on "Edit my membership" link.
Click the "Unsubscribe" button.
Note: This appears to be the most reliable way to unsubscribe
 
Alternately, send email to CLIPSESG-u...@googlegroups.com. You will receive an email which you must respond to as well to unsubscribe. Clicking the link mentioned in the unsubscribe reply does not appear to work reliably.
---
You received this message because you are subscribed to the Google Groups "CLIPSESG" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clipsesg+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/clipsesg/3475357e-3f7b-49b3-adec-5fcf2f41e7fen%40googlegroups.com.


--
Jim Allison, Ph.D., P.E.

CLIPS Support

unread,
Aug 6, 2023, 12:44:40 AM8/6/23
to CLIPSESG
If you're using the makefile that comes with CLIPS, that's not going to include the file EulersNumber.c, so when the makefile executes there won't be any command to compile EulersNumber.c into the object file EulersNumber.o, and that object file won't be included in the list of object files to link. You'll need to modify the makefile, so that EulersNumber.c is compiled and linked, or if you don't want to fiddle with that file, just issue a gcc -o clips *.c -lm command to compile and link all the files in the source directory.

Also, edit EulersNumber.h to include clips.h:

#include "clips.h"


void EulersNumber(Environment *,UDFContext *,UDFValue *);

and EulerNumber.c to include EulersNumber.h:

#include "EulersNumber.h"


#include <math.h>

void EulersNumber(
                  Environment *env,
                  UDFContext *udfc,
                  UDFValue *out)
{
  out->floatValue = CreateFloat(env,exp(1.0));
}

Jimmy Allison

unread,
Aug 7, 2023, 4:37:47 PM8/7/23
to clip...@googlegroups.com
Thanks again for your recent reply.

The following link error occurred when a C program containing a reference to the Posix shared memory function shm_open() was added as a UDF. 

gcc -o clips main.o -L. -lclips -lm                                                                                                                                                                                                                                                                                   

/usr/bin/ld: ./libclips.a(geographic_region.o): in function `geographic_region':                                                                                                                                                                                                                                      

geographic_region.c:(.text+0x79): undefined reference to `shm_open'                                                                                                                                                                                                                                                   

collect2: error: ld returned 1 exit status                                                                                                                                                                                                                                                                            

make: *** [makefile:94: clips] Error 1     

After adding the #include <sys/mman.h> to the userfunctions.c, geographic_region.c, and geographic_region.h the problem persists.

Below are each of these codes as I have attempted to use them:

userfunctions.c

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <unistd.h>

#include <string.h>


#include "clips.h"


#include "geographic_region.h"


void UserFunctions(Environment *);


void UserFunctions(

  Environment *env)

{


  {

    AddUDF(env,"geographic_region","sy",0,0,NULL,geographic_region,"geographic_region",NULL);

  }


#if MAC_XCD

#pragma unused(env)

#endif

}


geographic_region.c

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <unistd.h>

#include <string.h>

                                                                                                                                                                                                                                                                                         

#include "geographic_region.h"


#define SHARED_MEM_NAME "/jims"

#define EXIT_SUCCESS 0


struct shared_memory {

  char region[14];

  int n;

  float tt[2000][2000];

  int pa_bt[2000];

};


//int main(int argc, char **argv) {                                                                                                                                                                                                                                                                                   

void geographic_region(

                       Environment *env,

                       UDFContext *udfc,

                       UDFValue *out)

{


  printf("Entering geographic_region.c\n");

  struct shared_memory *shared_mem_ptr;

  int fd_shm;

  FILE *fromR;

  char region[14];

  int n;

  float times[2000];

  int pa_bt[2000];


  /* // Establish the shared memory. */


  if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDWR | O_CREAT | O_EXCL, 0666)) == -1)

    perror ("shm_open");


  if (ftruncate (fd_shm, sizeof (struct shared_memory)) == -1)

    perror("ftruncate");


  if ((shared_mem_ptr = mmap (NULL, sizeof (struct shared_memory), PROT_READ | PROT_WRITE, MAP_SHARED,

                              fd_shm, 0)) == MAP_FAILED)

    perror("mmap");


  /* // Write the R-generated OSRM matrix into shared memory. */


  fromR = fopen("time_matrix", "r");

  fscanf(fromR, "%s", region);

  sprintf(shared_mem_ptr -> region, "%s", region);

  printf("%s\n", region);

  fscanf(fromR, "%d", &n);

  shared_mem_ptr -> n = n;

  for(int i = 0; i < n; i++) {

    for (int j = 0 ; j < n; j++) {

      fscanf(fromR, "%f", &times[j]);

      shared_mem_ptr -> tt[i][j] = times[j];

    }

  }

  for(int i = 0; i < n; i++) {

    fscanf(fromR, "%d", &pa_bt[i]);

    shared_mem_ptr -> pa_bt[i] = pa_bt[i];

    printf("%d\n", pa_bt[i]);

  }

  

  //  return EXIT_SUCCESS;                                                                                                                                                                                                                                                                                            

  out->lexemeValue = CreateString(env, region);

}


and geographic_region.h

#include "clips.h"


#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <unistd.h>

#include <string.h>



void geographic_region(Environment *,UDFContext *,UDFValue *)


I see, by grepping within the core directory, CLIPS employs a number of system libraries. Is there something more that is required because the library for the Posix shared memory is within directory sys?

Perhaps I am missing where the #include should be added within the CLIPS infrastructure or maybe there is a flag needed? If an additional flag is required how is that included in the make process?

Thank you for your past help and any help you can provide in this matter.

Jim Allison 



CLIPS Support

unread,
Aug 7, 2023, 6:53:33 PM8/7/23
to CLIPSESG

I didn't get an undefined reference message when creating an executable with your code using Ubuntu or macOS Darwin, but a web search on "which library contains shm_open" indicates that the -lrt option is probably what you need to include (e.g. gcc -o clips *.c -lm -lrt).

Jimmy Allison

unread,
Aug 10, 2023, 9:35:49 PM8/10/23
to clip...@googlegroups.com
Hello,

In the below code I can call the UDF travel_time a seemingly unlimited number of times. However, when the rule R1 is executed it presents the error and terminates the clips process:

shm_open: Too many open files                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

mmap: Bad file descriptor                                                                                                                                                                                                                                                                                                                                                                                                                                                                              

Segmentation fault (core dumped)                                   

(travel_time 888653 1287831)

(travel_time 1287831 888653)


(defrule R1

   (SP_bt_avail ?bt ?bt_dow ?bt_setting ?bt_start ?bt_end)

   (test (eq ?bt 2243859))

   (SP_pa_avail ?pa ?pa_dow ?pa_setting ?pa_start ?pa_end)

   (test (eq ?pa_dow ?bt_dow))

   =>

   (printout t "Travel Time = " (travel_time ?bt ?pa) crlf)

   (printout t "Found pa " ?pa " " ?pa_dow " " ?pa_setting " " ?pa_start " " ?pa_end crlf)

   (printout t "Found bt " ?bt " " ?bt_dow " " ?bt_setting " " ?bt_start " " ?bt_end crlf))

In the C code I do ummap the Posix shared memory segment. 
Does CLIPS internally start a great number of executions of a rule such as R1 and then not conclude them for some time, leaving too many open files?
Is there a means to control such a situation if indeed that is what is happening?
Thank you

CLIPS Support

unread,
Aug 11, 2023, 1:00:01 AM8/11/23
to CLIPSESG
No, rules are executed one at a time are there's no I/O associated with executing a rule unless you're explicitly calling an I/O function.

Jimmy Allison

unread,
Aug 11, 2023, 7:44:29 AM8/11/23
to clip...@googlegroups.com
The below block of code is being run out of emacs to shorten the development cycle:

/home/ubuntu/clips/clips_core_source_640/core/clips

(load-facts "/home/ubuntu/Graphics/ABS_Scheduling_Optimization/intermediate_files/facts_in")

(defrule R1

   (SP_bt_avail ?bt ?bt_dow ?bt_setting ?bt_start ?bt_end)

   (SP_pa_avail ?pa ?pa_dow ?pa_setting ?pa_start ?pa_end)

   (test (eq ?bt 2243859))

   (test (eq ?pa_dow ?bt_dow))

   =>

   (bind ?tt (travel_time ?bt ?pa))

   (printout t "Travel Time = " ?tt crlf)

   (printout t ?bt " " ?pa crlf))

(run)


When the two lines involving the variable ?tt are commented out, all invocations of the rule run successfully and the clips prompt is returned. When uncomment, many invocations are executed but ultimately terminates as shown below:

2243859 1863309                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

Unmapping result is 0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

Travel Time = 59.0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

2243859 1863185                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

Unmapping result is 0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

Travel Time = 137.0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

2243859 1862346                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

Unmapping result is 0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

Travel Time = 96.0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

2243859 1861660                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

Segmentation fault (core dumped)                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

(base) ubuntu@ip-172-31-11-209:~/clips/clips_core_source_640/core$     


The reoccuring line, "Unmapping result is 0" is a line I inserted into the UDF to see if the munmap was not being accomplished. A zero indicates the call was successful.

Can there be an explanation for what I am seeing?
Could it be, CLIPS just needs to be slowed down? If such is the case, can you foresee a UDF to sleep for a short period of time, when called from the rule, as potentially useful to provide more time between successive calls to the UDF accessing shared memory?

Thank you.

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <unistd.h>

#include <sys/types.h>


#include "travel_time.h"


#define SHARED_MEM_NAME "/jims"


struct shared_memory {

  char region[14];

  int n;

  float tt[2000][2000];

  int pa_bt[2000];

};


/* char* check() { */

/*   printf("Entering check.\n"); */

/*   return "Zone 27"; */

/* } */


/* float main(int argc, char *argv[]) { */

void travel_time(

                 Environment *env,

                 UDFContext *udfc,

                 UDFValue *out)

{

  UDFValue from, to;

  

  struct shared_memory *shared_mem_ptr;

  int fd_shm;

  FILE *fromR;

  int n;

  //  int from, to;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

  /* char* check_return; */


  /* check_return = check(); */

  /* printf("Check Return %s\n", check_return); */


  UDFFirstArgument(udfc,INTEGER_BIT,&from);

  UDFNextArgument(udfc,INTEGER_BIT,&to);


  long long From = from.integerValue->contents;

  long long To   = to.integerValue->contents;

  long long F, T;


  // Connect to the shared memory.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

  

  if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDONLY, 0666)) == -1)

    perror("shm_open");


  if ((shared_mem_ptr = mmap ( NULL, sizeof (struct shared_memory), PROT_READ, MAP_SHARED,

                              fd_shm, 0)) == MAP_FAILED)

    perror("mmap");


  // Determine the travel time.                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

  

  n = shared_mem_ptr -> n;

  //  printf("The count n is %d\n", n);                                                                                                                                                                                                                                                                                                                                                                                                                                                                

  for(int i = 0; i < n; i++) {

    if(From == shared_mem_ptr -> pa_bt[i])

      F = i;

    if(To == shared_mem_ptr -> pa_bt[i])

      T = i;

  }


  //  printf("Indicies are from = %lld and to = %lld\n", F, T);                                                                                                                                                                                                                                                                                                                                                                                                                                        

  /* printf("Travel time is %f\n", shared_mem_ptr -> tt[from - 1][to - 1]); */


  /* return shared_mem_ptr -> shared_mem_pr->tt[from - 1][to - 1]; */

  out->floatValue = CreateFloat(env,shared_mem_ptr->tt[F - 1][T - 1]);


  //  munmap(void addr[.length], size_t length);                                                                                                                                                                                                                                                                                                                                                                                                                                                       

  int result  = munmap(NULL, sizeof (struct shared_memory));

  printf("Unmapping result is %d\n", result);


}








CLIPS Support

unread,
Aug 11, 2023, 5:44:09 PM8/11/23
to CLIPSESG
I would suggest first validating that your code works independently of CLIPS. If you need to sleep to get your code to work properly, you should do that from within the UDF, but if you wanted to do it from your rule before the UDF is called, you can place a (system "sleep 3") command in the actions of the rule to invoke the unix sleep command.

I tried running your code independent of CLIPS in both Ubuntu and macOS Darwin and I get segmentation faults on the very first call to travel_time.

#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>

//#include "travel_time.h"


#define SHARED_MEM_NAME "/jims"

struct shared_memory {
  char region[14];
  int n;
  float tt[2000][2000];
  int pa_bt[2000];
};

/* char* check() { */
/*   printf("Entering check.\n"); */
/*   return "Zone 27"; */
/* } */

void travel_time(long long,long long);

int main()
  {
   travel_time(2243859,1863309);
   travel_time(2243859,1863185);
   travel_time(2243859,1862346);
   travel_time(2243859,1861660);

  }
 
/* float main(int argc, char *argv[]) { */
void travel_time(long long From,
                 long long To)
{

  struct shared_memory *shared_mem_ptr;
  int fd_shm;
  FILE *fromR;
  int n;

  long long F, T;

  // Connect to the shared memory.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
 
  if ((fd_shm = shm_open (SHARED_MEM_NAME, O_RDONLY, 0666)) == -1)
    perror("shm_open");

  if ((shared_mem_ptr = mmap ( NULL, sizeof (struct shared_memory), PROT_READ, MAP_SHARED,
                              fd_shm, 0)) == MAP_FAILED)
    perror("mmap");

  // Determine the travel time.                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
 
  n = shared_mem_ptr -> n;
  printf("The count n is %d\n", n);                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  for(int i = 0; i < n; i++) {
    if(From == shared_mem_ptr -> pa_bt[i])
      F = i;
    if(To == shared_mem_ptr -> pa_bt[i])
      T = i;
  }

  printf("Indicies are from = %lld and to = %lld\n", F, T);                                                                                                                                                                                                                                                                                                                                                                                                                                        
  //printf("Travel time is %f\n", shared_mem_ptr -> tt[from - 1][to - 1]);

  /* return shared_mem_ptr -> shared_mem_pr->tt[from - 1][to - 1]; */
  double out = shared_mem_ptr->tt[F - 1][T - 1];


  //  munmap(void addr[.length], size_t length);                                                                                                                                                                                                                                                                                                                                                                                                                                                      
  int result  = munmap(NULL, sizeof (struct shared_memory));
  printf("Unmapping result is %d\n", result);

}
Reply all
Reply to author
Forward
0 new messages