I\'m working with a binary search tree data structure to sort a series of structs with the type definitions:
typedef struct {
    char c;
    int index;
} da         
        Sure it's possible, you'd cast key as type *data_t.  (As long as that's really what key points to!)
key                     /* argument of type void* */
(data_t*)key            /* cast as type data_t*   */
((data_t*)key)->index   /* dereferenced */
Here is a simple example:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
    char    c;
    int     index;
} data_t;
typedef struct node {
    void    *data;
    struct node *left;
    struct node *right;
} node_t;
static int cmp(void *lhs, void *rhs)
{
    return ((data_t *)lhs)->index - ((data_t *)rhs)->index;
}
int main(void)
{
    data_t d0;
    data_t d1;
    d0.c     = 'A';
    d0.index = 1;
    d1.c     = 'B';
    d1.index = 2;
    printf("d0 < d1? %s\n", (cmp((void *)&d0, (void *)&d1) < 0 ? "yes" : "no"));
    printf("d1 < d0? %s\n", (cmp((void *)&d1, (void *)&d0) < 0 ? "yes" : "no"));
    return EXIT_SUCCESS;
}
This is type unsafe, as is any use of void. The use of void is generally because the intermediate is holding onto something it doesn't use for someone else's convenience. This is a C function to let you hold whatever you want in a tree. All it does is return whatever pointer you give it.
In your search function
int cmp(void* dt1, void* dt2)
{
data_t*  data1 = (data_t*)dt1;
data_t*  data2 = (data_t*)dt2;
/* Do what you need with data1 and data2 here */
}
Should let you do whatever you need. The problem you have is you need to cast your values inside the function. The parameters to cmp should exactly match the API for the library you are using, which says void* for the parameters.