Error C2440 with TinyCC

Hello,

I am trying to get the intertwining spiral example from libGE (a grammatical evolution library) compiled and running with tinycc and I come up with 2 errors at compile time.

error C2440: '=' : cannot convert from 'void *' to 'int (__cdecl *)(int)'
Conversion from 'void*' to pointer to non-'void' requires an explicit cast
error C2440: '=' : cannot convert from 'void *' to 'int (__cdecl *)(int)'
Conversion from 'void*' to pointer to non-'void' requires an explicit cast

Here is what I believe to be the relevant code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    /* create tcc state */
    TCCState *s;
	int (*func)(int);
	int (*fitnessfunc) (int);
    void *mem;
    int size;
	
	s = tcc_new();
    if (!s) 
	{
		fprintf(stderr, "Could not create tcc state\n");
		exit(1);
    }
    tcc_set_output_type(s, TCC_OUTPUT_MEMORY);

    /* add the math library */
    tcc_add_library(s, "m");

    /* Compile the GE functions in the tcc state */
    if (tcc_compile_string(s, GEfunc) != 0) {
      fprintf(stderr, 
	      "Error in GEspiral.c TCC string compilation!, Exiting!\n");
      exit(-1);
    }

    string buffer;
    //Write start code to buffer
    buffer = ISstart;
    //Write phenotype code to buffer
    buffer += phenotype->getString();
    //Write end code to buffer
    buffer += ISend;

    // Compile the buffer.
    if (tcc_compile_string(s, buffer.c_str()) != 0) {
      fprintf(stderr, "Error in phenotype TCC compilation!, Exiting!\n");
      exit(-1);
    }
	
	size = tcc_relocate(s, NULL);
    if (size == -1)
        return 1;

	mem = malloc(size);
    if (tcc_relocate(s, mem) != 0) {
      fprintf(stderr, "Error tcc_relocate failed, Exiting!\n");
      exit(-1);
    }
					
    // Get pointer to the main function symbol.
    func = tcc_get_symbol(s, "main");
    if (!func) {
      fprintf(stderr, "Error: could not tcc_get_symbol main, Exiting");
      exit(-1);
    }
				
    // Execute the main function.
	func(32);

					
    // Get the fitness function symbol.
    fitnessfunc = tcc_get_symbol(s, "AssignFitness");


The errors are specific to the lines:

1
2
3
func = tcc_get_symbol(s, "main");
// and
fitnessfunc = tcc_get_symbol(s, "AssignFitness");


I am compiling on Windows Vista with MS Visual Studio 2008.
I am using a modified GAlib 2.4.7 http://lancet.mit.edu/ga/
an unmodified libGE 0.26 http://bds.ul.ie/libGE/
and Tiny C Compiler 0.9.25 http://bellard.org/tcc/

If you require any further information or code please ask, I am happy to provide.

P.S. If I comment out the relevant parts of the code I get no further compile errors, but I do get several linker errors.
Like the error message says, in C++, you can't cast from void * to non-void * implicitly. You have to explicitly perform the cast. For example:
int *a=(int *)malloc(sizeof(int));
I understand that but explicitly performing the cast doesn't fix the problem, it only changes it from this:

error C2440: '=' : cannot convert from 'void *' to 'int (__cdecl *)(int)'
Conversion from 'void*' to pointer to non-'void' requires an explicit cast

to this

error C2440: '=' : cannot convert from 'int *' to 'int (__cdecl *)(int)'
There is no context in which this conversion is possible

Forgive me but I still dont understand how to fix the problem.

Also I though it might be helpful to add the specific tinyCC function here so people don't have to search for it:

1
2
3
4
5
6
7
8
9
10
void *tcc_get_symbol(TCCState *s, const char *name)
{
    int sym_index;
    ElfW(Sym) *sym;
    sym_index = find_elf_sym(symtab_section, name);
    if (!sym_index)
        return NULL;
    sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
    return (void*)(long)sym->st_value;
}

Uh... My snippet was just an example. If you're trying to assign to a pointer that's not int *, then quite obviously casting to int * will not solve anything. The compiler is flat-out telling you what the type you should cast to is.

EDIT: Oh, and in your function, don't cast to long before casting to void *. They may not be the same size and it cause trouble.
Last edited on
I think you misunderstood what Helios was saying.
tcc_get_symbol function returns void *.
You need to convert this void pointer to a pointer to function that takes an integer parameter and returns an int because that is what func is declared as


This is what this error error C2440: '=' : cannot convert from 'void *' to 'int (__cdecl *)(int)' is trying to tell you.
So you need to do an explicit (specified by programmer) cast conversion - because the compiler is not going to do it automatically (implicitly) for you.

Explicit casting using C style cast (ugly).
func = (int (*) (int) ) tcc_get_symbol(s, "main");

To make it less ugly looking you can make use of typedef - do you know how to use typedef ??
Ahha, I had tried something almost identical to what guestgulkan posted but I did not realize that i had to put the parentheses around the asterix. Yes I know how to use typedef I just hardly use them and so were not the first things to come to mind.

@helios as for the casting to long before void* in the function, that was how tinyCC was programed and since I only need it to play around with the examples I don't feel like changing it and then dealing with the compile errors that might ensue.

Thanks.
Topic archived. No new replies allowed.