convert function pointer to C++

I have the following function declarations and the function call that works in C. I want to convert the code to C++, but unable to cast it to the correct types.

// definition of functions
static unsigned long (*putcharfunc)(char c, unsigned long);

void rprintf_devopen( unsigned long(*put)(char, unsigned long))
{
putcharfunc = put;
}

int uart0_putchar (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}


// calling from main.cpp
rprintf_devopen(uart0_putchar);


Errors:

../main.cpp:367: error: invalid conversion from 'int (*)(int)' to 'long unsigned int (*)(char, long unsigned int)'
../main.cpp:367: error: initializing argument 1 of 'void rprintf_devopen(long unsigned int (*)(char, long unsigned int))'
uart0_putchar does not take 2 arguments. The function pointer does. I am very surprised that compiles in C, it shouldn't do, not without generating lots of warnings.
When I compile the file as a C file, here's the warning I get.

../main.c:367: warning: passing argument 1 of 'rprintf_devopen' from incompatible pointer type
Well, that's a big problem with C. The code makes no sense and yet it only issues one warning.

uart0_putchar is a function that takes 1 argument.
rprintf_devopen takes a pointer to a function that accepts two arguments.

So it makes no sense to pass uart0_putchar to rprintf_devopen.
Well, C does this correct. Techically you can pass two or more arguments to the function that expects only one argument - this won't break at the binary level. That is why warning is ok here and the code works. However, it would probably fail the other way round - if you passed only one argument to a two argument function. Probably the called function would get some garbage then as a second argument (but still it wouldn't segfault).

C is a weakly-typed language with a philosophy "programmer is always right - if he wants me to do this, I'll do". C++ is also a weakly-typed language, but a bit hardened, so some of the C warnings now became errors. Therefore it is slightly harder to shoot yourself in a foot (but still easy to get the whole leg blown away).
Last edited on
That case doesn't break on the binary level, but you can't generalize that can you?

Consider that the function pointer takes two char arguments and you assign it a function that takes an int. Surely this would break?
The code has instances where sometimes there are two arguments and in other cases only one. Just so we focus on the type conversion, I changed the function only to a one argument function and redid the problem. The results are exactly the same.

void rprintf_devopen( unsigned long(*put)(char) );

static unsigned long (*putcharfunc)(char c);

void rprintf_devopen( unsigned long(*put)(char))
{
putcharfunc = put;
}

int uart0_putchar (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}


//Compiled as a C file
../main.c:367: warning: passing argument 1 of 'rprintf_devopen' from incompatible pointer type


//Compiled as a C++ file
../main.cpp:367: error: invalid conversion from 'int (*)(char)' to 'long unsigned int (*)(char)'
../main.cpp:367: error: initializing argument 1 of 'void rprintf_devopen(long unsigned int (*)(char))'
Return types still differ, as does argument. The following compiles fine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static unsigned long (*putcharfunc)(char);

void rprintf_devopen( unsigned long(*put)(char) )
{
putcharfunc = put;
}

unsigned long uart0_putchar (char ch)
{
}

int main() {
	rprintf_devopen(uart0_putchar);
	return 0;
}
I thought I could use a type casting to do this, but didn't work.

rprintf_devopen(dynamic_cast<unsigned long*>(uart0_putchar));

My final solution was to change the function type.
I converted the function type and the problem went away in both C and C++.

unsigned long uart0_putchar (char ch);

did we come up with the same solution?
Why do you say the return types still differ when you actually converted to the same type?
What I meant was those were the issues stopping yours from compiling, so I fixed them both in my code.
Agree. Thanks for your time on the discussion.
Topic archived. No new replies allowed.