Version 3 (modified by jorisborgdorff, 12 years ago) (diff)

--

The C API of MUSCLE is a subset of the C++ API, the C API is again a subset of the Java API. Because the core of MUSCLE is written in Java, any C++ executable will communicate with Java code, but this is hidden in the API. In both cases, the include path is $MUSCLE_HOME/include

C API

All muscle2 headers are installed in $MUSCLE_HOME/include/muscle2. The header for the C API is muscle2/cmuscle.h.

The functions there are very limited, but they should be sufficient for most needs:

muscle_error_t MUSCLE_Init(int* argc, char*** argv);
void MUSCLE_Finalize(void);

const char* MUSCLE_Get_Kernel_Name(void);
const char* MUSCLE_Get_Property(const char* name);
int MUSCLE_Will_Stop(void);

muscle_error_t MUSCLE_Send(const char *exit_name, void *array, size_t size, muscle_datatype_t type);
void* MUSCLE_Receive(const char *entrance_name, void *array, size_t *size, muscle_datatype_t type);

The MUSCLE_Init function must be called before any of the other MUSCLE functions is used, and also before MPI_Init is called, if MPI is used. The usage is the same of MPI_Init: to initialize MUSCLE given the current arguments of main. After all MUSCLE calls have been made, MUSCLE_Finalize should be called. Usually:

int main(int argc, char *argv[])
{
    MUSCLE_Init(&argc, &argv);
    ...
    MUSCLE_Finalize();
    return 0;
}

After this, any code can be written. The MUSCLE_Get_Kernel_Name function gives the current kernel name. This must be freed after use. Similarly, MUSCLE_Get_Property gives a property as a string, which must be freed afterwards.

The send and receive functions can transport several datatypes, which are enumerated in muscle2/muscle_types.h. For reference, it takes the following datatypes

muscle_datatype_tC data type Java data type maximum size
MUSCLE_DOUBLEdouble *double[]134e6 values
MUSCLE_FLOATfloat *float[]268e6 values
MUSCLE_INT32int *int[]268e6 values
MUSCLE_INT64long *long[]134e6 values
MUSCLE_STRINGchar *String64e3 characters
MUSCLE_RAWunsigned char *byte[]268e6 values
MUSCLE_COMPLEXmuscle::ComplexData *any other object1 GiB

The type MUSCLE_COMPLEX is only available for C++ code.

Receiving a message can be done in two ways: either the memory is initialized beforehand and the buffer size is given as the third argument, or a 0 pointer is passed, in which case MUSCLE will initialize the memory. In both cases, the memory must be freed by the user. For example:

size_t sz = 100;
double *data = (double *)malloc(sz*sizeof(double));
if (data) {
    for (int i = 0; !MUSCLE_Will_Stop(); i++) {
        MUSCLE_Receive("exitName", data, &sz, MUSCLE_DOUBLE);
        // do something with the data
    }
    free(data);
}

or

size_t sz = 0;
for (int i = 0; !MUSCLE_Will_Stop(); i++) {
    double *data = (double *)MUSCLE_Receive("exitName", (void *)0, &sz, MUSCLE_DOUBLE);
    // do something with the data
    // data will have length sz;
    free(data);
}