I'm not first and not last I mean)
And it's one more question about waring: assignment makes pointer from integer without a cast.
I've already read this and this and this and this and this and more and more.
I have NUCLEO-F070RB-STM32 devkit. And I want to send different messages on PC for debugging.
I use this construction:
uint8_t greeting[] = "Welcome to first circle of hell\n";
HAL_UART_Transmit(&huart2, greeting, sizeof(greeting)-1, 30);
//"sizeof(greeting)-1" cut "\0" from string
Here is a description:
/**
* #brief Send an amount of data in blocking mode.
* #note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* the sent data is handled as a set of u16. In this case, Size must indicate the number
* of u16 provided through pData.
* #note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
* address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits)
* (as sent data will be handled using u16 pointer cast). Depending on compilation chain,
* use of specific alignment compilation directives or pragmas might be required
* to ensure proper alignment for pData.
* #param huart UART handle.
* #param pData Pointer to data buffer (u8 or u16 data elements).
* #param Size Amount of data elements (u8 or u16) to be sent.
* #param Timeout Timeout duration.
* #retval HAL status
*/
And all work perfectly.
But I want different message. I'm a good programmer.
uint8_t greeting[] = "Welcome to first circle of hell\n";
uint8_t str[] = "just for UART\r\n";
void send_to_uart (uint8_t);
void send_to_uart (uint8_t it_will_be_send)
{
HAL_UART_Transmit(&huart2, it_will_be_send, sizeof(it_will_be_send)-1, 30);
}
int main(void)
{
send_to_uart(greeting);
wile (1)
{
send_to_uart(str);
}
}
And I have a warning and have no data on my screen.
Bad bad bad programmer!
I understand that devil in pointers.
But can you explain slowly step by step for all newbies like me:
How to pass ...n arrays to functions. PLEEEAASEEE
P.S.
/* USER CODE BEGIN 0 */
void send_to_uart (uint8_t);
void send_to_uart (uint8_t it_will_be_send)
{
HAL_UART_Transmit(&huart2, it_will_be_send, sizeof(it_will_be_send)-1, 30);
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE BEGIN WHILE */
uint8_t greeting[] = "\nWelcome to first circle of hell\n";
uint8_t some_string[] = "some string to UART\r\n";
send_to_uart(greeting);
HAL_UART_Transmit(&huart2, greeting, sizeof(greeting)-1, 30);
while (1)
{
HAL_UART_Transmit(&huart2, "\nHAL some string to UART\n" , 25, 30);
send_to_uart(some_string);
HAL_UART_Transmit(&huart2, some_string, sizeof(some_string)-1, 30);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
make -j4 all
arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m0 -std=gnu11 -g3 -DDEBUG -DUSE_HAL_DRIVER -DSTM32F070xB -c -I../Core/Inc -I../Drivers/STM32F0xx_HAL_Driver/Inc -I../Drivers/STM32F0xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32F0xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o"
../Core/Src/main.c: In function 'send_to_uart':
../Core/Src/main.c:67:29: warning: passing argument 2 of 'HAL_UART_Transmit' makes pointer from integer without a cast [-Wint-conversion]
67 | HAL_UART_Transmit(&huart2, it_will_be_send, sizeof(it_will_be_send)-1, 30);
| ^~~~~~~~~~~~~~~
| |
| uint8_t {aka unsigned char}
In file included from ../Core/Inc/stm32f0xx_hal_conf.h:288,
from ../Drivers/STM32F0xx_HAL_Driver/Inc/stm32f0xx_hal.h:30,
from ../Core/Inc/main.h:31,
from ../Core/Src/main.c:21:
../Drivers/STM32F0xx_HAL_Driver/Inc/stm32f0xx_hal_uart.h:1491:73: note: expected 'uint8_t *' {aka 'unsigned char *'} but argument is of type 'uint8_t' {aka 'unsigned char'}
1491 | HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
| ~~~~~~~~~^~~~~
../Core/Src/main.c: In function 'main':
../Core/Src/main.c:112:16: warning: passing argument 1 of 'send_to_uart' makes integer from pointer without a cast [-Wint-conversion]
112 | send_to_uart(greeting);
| ^~~~~~~~
| |
| uint8_t * {aka unsigned char *}
../Core/Src/main.c:65:28: note: expected 'uint8_t' {aka 'unsigned char'} but argument is of type 'uint8_t *' {aka 'unsigned char *'}
65 | void send_to_uart (uint8_t it_will_be_send)
| ~~~~~~~~^~~~~~~~~~~~~~~
../Core/Src/main.c:117:29: warning: pointer targets in passing argument 2 of 'HAL_UART_Transmit' differ in signedness [-Wpointer-sign]
117 | HAL_UART_Transmit(&huart2, "\nHAL some string to UART\n" , 25, 30);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from ../Core/Inc/stm32f0xx_hal_conf.h:288,
from ../Drivers/STM32F0xx_HAL_Driver/Inc/stm32f0xx_hal.h:30,
from ../Core/Inc/main.h:31,
from ../Core/Src/main.c:21:
../Drivers/STM32F0xx_HAL_Driver/Inc/stm32f0xx_hal_uart.h:1491:73: note: expected 'uint8_t *' {aka 'unsigned char *'} but argument is of type 'char *'
1491 | HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
| ~~~~~~~~~^~~~~
../Core/Src/main.c:118:15: warning: passing argument 1 of 'send_to_uart' makes integer from pointer without a cast [-Wint-conversion]
118 | send_to_uart(some_string);
| ^~~~~~~~~~~
| |
| uint8_t * {aka unsigned char *}
../Core/Src/main.c:65:28: note: expected 'uint8_t' {aka 'unsigned char'} but argument is of type 'uint8_t *' {aka 'unsigned char *'}
65 | void send_to_uart (uint8_t it_will_be_send)
| ~~~~~~~~^~~~~~~~~~~~~~~
arm-none-eabi-gcc -o "max6675_2.0.elf" #"objects.list" -mcpu=cortex-m0 -T"C:\stm32\cubeMX_workspace\max6675_2.0\STM32F070RBTX_FLASH.ld" --specs=nosys.specs -Wl,-Map="max6675_2.0.map" -Wl,--gc-sections -static --specs=nano.specs -mfloat-abi=soft -mthumb -Wl,--start-group -lc -lm -Wl,--end-group
Finished building target: max6675_2.0.elf
arm-none-eabi-objdump -h -S max6675_2.0.elf > "max6675_2.0.list"
arm-none-eabi-objcopy -O binary max6675_2.0.elf "max6675_2.0.bin"
arm-none-eabi-size max6675_2.0.elf
text data bss dec hex filename
8228 20 1804 10052 2744 max6675_2.0.elf
Finished building: default.size.stdout
Finished building: max6675_2.0.bin
Finished building: max6675_2.0.list
13:39:29 Build Finished. 0 errors, 4 warnings. (took 1s.941ms)
Look at this:
void send_to_uart (uint8_t);
So send_to_uart expect an argument of type uint8_t - fine.
Now look at this:
uint8_t greeting[] = "Welcome to first circle of hell\n";
int main(void)
{
send_to_uart(greeting); <--- What is greeting?
So is greeting a uint8_t ?
No - it's not. It's an array so you can't pass it to a function that expects a uint8_t
Try like:
for (int i = 0; i < strlen(greeting); ++i) send_to_uart(greeting[i]);
Related
I have this header and function defined in it called long ptr = PT_REGS_PARM2(ctx); so first running command like following assuming my system config will take care of it finding this header file in /usr/include/bpf/tracing.h.
but couldn't find the header file
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -I /usr/include/ -c kprobe_send.c -o kprobe_send.o
I also tried with - I and changing <bpf/tracing.h> to "bpf/tracing.h" not worked either.
I started this inclusion of -I after I was compiling this program and it causing error on compile, I could not understand the error but this is following
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g-target bpf -c kprobe_send.c -o kprobe_send.o
clang: error: unknown argument: '-g-target'
clang: error: no such file or directory: 'bpf'
root#this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -O2 -Wall -g -target bpf -c kprobe_send.c -o kprobe_send.o
kprobe_send.c:31:2: warning: implicit declaration of function 'srand' is invalid in C99 [-Wimplicit-function-declaration]
srand(time(NULL)); /* Seed the random number generator. */
^
kprobe_send.c:37:11: warning: implicit declaration of function 'rand' is invalid in C99 [-Wimplicit-function-declaration]
int c = randrange(MAX-i);
^
kprobe_send.c:11:22: note: expanded from macro 'randrange'
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
^
kprobe_send.c:51:22: warning: implicit declaration of function 'PT_REGS_PARM2' is invalid in C99 [-Wimplicit-function-declaration]
char *ptr = PT_REGS_PARM2(ctx);
^
kprobe_send.c:51:15: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]
char *ptr = PT_REGS_PARM2(ctx);
^ ~~~~~~~~~~~~~~~~~~
kprobe_send.c:61:22: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'void *' [-Wint-conversion]
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
^~
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
fatal error: error in backend: Cannot select: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11
0x18af668: i64 = sra 0x189bcd8, Constant:i64<32>, kprobe_send.c:37:11
0x189bcd8: i64 = shl 0x189c4f8, Constant:i64<32>, kprobe_send.c:37:11
0x189c4f8: i64,ch,glue = CopyFromReg 0x189c018, Register:i64 $r0, 0x189c018:1, kprobe_send.c:37:11
0x189c150: i64 = Register $r0
0x189c018: ch,glue = callseq_end 0x189bc08, TargetConstant:i64<0>, TargetConstant:i64<0>, 0x189bc08:1, kprobe_send.c:37:11
0x189bfb0: i64 = TargetConstant<0>
0x189bfb0: i64 = TargetConstant<0>
What the above error even means, I thought it was complaining I did not include any headers so I started including tracing.h to cater to PT_REGS_PARM2(ctx)
How can I get rid of this error?
On this line it says unsupported sign division:
Error at line 37: Unsupport signed division for DAG: 0x18aff58: i64 = sdiv 0x18af668, 0x18afe20, kprobe_send.c:37:11Please convert to unsigned div/mod.
Is this line 37 referring to assembly or my source file? In line 37 of source file I am doing
int c = randrange(MAX-i);
Why is the above simple line is not allowed in ebpf program? This is my line 37 and rest of the bpf program
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
//#include <bpf/tracing.h>
#include <stdlib.h>
#define RAND_MAX 0x7fff
#define PERF_SAMPLE_RAW 1U << 0
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
#define MAX 100000000 /* Values will be in the range (1 .. MAX) */
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
__uint(max_entries, 100);
} my_map SEC(".maps");
SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx,int fd, const char *buf, size_t count)
{
static int vektor[100000000];
int candidates[MAX];
int i;
long key;
srand(time(NULL)); /* Seed the random number generator. */
for (i=0; i<MAX; i++)
candidates[i] = i;
for (i = 0; i < MAX-1; i++) {
int c = randrange(MAX-i);
int t = candidates[i];
candidates[i] = candidates[i+c];
candidates[i+c] = t;
}
for (i=0; i<10; i++)
vektor[i] = candidates[i] + 1;
struct S {
int pid;
char cookie[90];
char *ptr;
} data={1,""};
char *ptr = PT_REGS_PARM2(ctx);
//data.pid =count;// bpf_get_current_pid_tgid();
//if(buf==NULL)
//memcpy(data.cookie,buf,20);
data.ptr=ptr;
// data.cookie[0]=buf[0];
//bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
key=vektor[i];
bpf_map_update_elem(fd,&key,&data,BPF_ANY);
//bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = 99;
is there any info source where it says what's allowed or what's not allowed because seems to me its just picking arbitrarily what's allowed and what's not looking into ebpf
My kernel: 5.14.1
My clang: 12
libbpf installed but I'd love to find a command that tells its version and or just where it's installed.
On some link I found it says maybe/or definitely (couldn't tell the difference) be a problem of symlink on Ubuntu exact source .. what this even means does it mean I installed libbpf or something and unbuntu messed up with my symlink that help find libbpf headers? How can I understand what this link says? https://github.com/iovisor/kubectl-trace/issues/76#issuecomment-513587108
The code here is a code from a website. Since I was facing an issue with my origin code, I ended up trying this implementation from a website. But turns out I have the same issue with this program too
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
FILE *fptr;
if ((fptr = fopen("D:\\TestFile\\test.txt","r")) == NULL){
printf("Error! opening file\n");
perror(fptr);
// Program exits if the file pointer returns NULL.
exit(1);
}
fscanf(fptr,"%d", &num);
printf("Value of n=%d\n", num);
printf("%s\n", fptr);
fclose(fptr);
return 0;
}
I am stuck with the if condition i.e., whatever I do I am not able to read the file except the root directory. Even though I specify the path, it still looks for the file under root directory.
I am not sure why it's not working, provided the same code works fine in Linux
I see 2 mistakes, the one related to perror mentioned in the comments, and the last printf. Now if the program is still not working, it could be interesting to check the error or to get the program output.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
FILE *fptr;
if ((fptr = fopen("D:\\TestFile\\test.txt","r")) == NULL){
// printf("Error! opening file\n");
// perror(fptr); // MISTAKE-1: perror parameter is a string
perror("Error! opening file");
// Program exits if the file pointer returns NULL.
exit(1);
}
fscanf(fptr,"%d", &num);
printf("Value of n=%d\n", num);
//printf("%s\n", fptr); // MISTAKE-2: fptr is not a string
fclose(fptr);
return 0;
}
the posted code does not cleanly compile!
Here is the results of compiling with many of the warnings enabled:
gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o"
untitled1.c: In function ‘main’:
untitled1.c:11:16: warning: passing argument 1 of ‘perror’ from incompatible pointer type [-Wincompatible-pointer-types]
11 | perror(fptr);
| ^~~~
| |
| FILE * {aka struct _IO_FILE *}
In file included from untitled1.c:1:
/usr/include/stdio.h:775:33: note: expected ‘const char *’ but argument is of type ‘FILE *’ {aka ‘struct _IO_FILE *’}
775 | extern void perror (const char *__s);
| ~~~~~~~~~~~~^~~
untitled1.c:19:13: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘FILE *’ {aka ‘struct _IO_FILE *’} [-Wformat=]
19 | printf("%s\n", fptr);
| ~^ ~~~~
| | |
| | FILE * {aka struct _IO_FILE *}
| char *
Compilation finished successfully.
Note; the statement: Compilation finished successfully. just means the compiler applied some work around to each of the problems. It does NOT mean the correct code was produced.
I am trying to implement my own heap memory allocator, by allocating memory via sbrk() system call, and managing the return buffer. void *sbrk(intptr_t increment); return value:
From man sbrk:
On success, sbrk() returns the previous program break. (If the
break was increased, then this value is a pointer to the start of the
newly allocated memory). On error, (void *) -1 is re‐
turned, and errno is set to ENOMEM
#include <gnu/libc-version.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
/*
puts (gnu_get_libc_version ());
*/
#define VP_ALIGNMENT (4096)
#define ALIGN(size,alignment) ( ((size) + (alignment-1)) & ~((alignment-1)) )
static void *extend_heap(int nbytes)
{
void *sp = sbrk(ALIGN(nbytes, VP_ALIGNMENT));
if (sp == (void*)-1) {
perror("fails to retrieve program brk");
}
return sp;
}
struct S{
char m[4096];
};
int main() {
/* get current brk */
void *cbrk = sbrk(0);
printf("current prog brk: %p\n",cbrk);
/*allocate 4096 bytes and get pointer to the start of the buffer*/
struct S *buf = (struct S*)extend_heap(4000);
printf("prog brk after allocation: %p\n",sbrk(0));
int c=4096;
do {
buf->m[4096-c] = 'a';
} while(--c);
c=4096;
do {
assert(buf->m[4096-c] == 'a');
} while(--c);
return 0;
}
Compile with gcc & gcc flags: cc main.c -pedantic -Wconversion -Werror
the program run as expected, but i dont understand why linux allocates a huge amount of memory, 2200hex bytes when i have asked only for 4096 ?
adding one of the gcc flags -ansi or -std=c89 produce compilation errors below:
In function ‘extend_heap’: main.c:15:20: error: initialization of
‘void *’ from ‘int’ makes pointer from integer without a cast
[-Werror=int-conversion] 15 | void *sp = sbrk(ALIGN(nbytes,
VP_ALIGNMENT));
| ^~~~ main.c: In function ‘main’: main.c:31:22: error: initialization of ‘void *’ from ‘int’ makes
pointer from integer without a cast [-Werror=int-conversion] 31 |
void *cbrk = sbrk(0);
| ^~~~
sbrk returns void*.
why I am getting the error above?
My glibc version = 2.31, gcc version 9.3.0
Thanks.
In order to make a good timing in an emulator, I have to wait for around 50 microseconds.
When I use nanosleep, for example with a duration of 10 microsecs, I measure a delay of 15 millisec ! I use mingw on windows with the following example code :
#include <stddef.h>
#include <time.h>
#include <stdio.h>
int main()
{
struct timespec startx, endx;
struct timespec req={0};
req.tv_sec=0;
req.tv_nsec=10000; // 10_000 ns = 10 microseconds
for (int i=0; i<10; i++)
{
clock_gettime(CLOCK_MONOTONIC, &startx);
nanosleep(&req, NULL);
clock_gettime(CLOCK_MONOTONIC, &endx);
if (endx.tv_sec-startx.tv_sec)
printf("%li microsecs\n",((endx.tv_nsec-startx.tv_nsec)/1000)+1000000);
else
printf("%li microsecs\n",(endx.tv_nsec-startx.tv_nsec)/1000);
}
return 0 ;
}
And the result is :
12528 microsecs
19495 microsecs
14890 microsecs
14229 microsecs
14657 microsecs
14824 microsecs
14724 microsecs
21074 microsecs
13697 microsecs
13893 microsecs
I guess I'm wrong somewhere....
If someone has an idea. I could also avoid the problem with a "do nop while (end-start) < 50usec"...
Thanks.
When I run the posted code through a compiler (gcc) the compiler outputs the following:
gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o"
untitled1.c: In function ‘main’:
untitled1.c:16:57: error: ‘err’ undeclared (first use in this function)
16 | if (nanosleep(&req, NULL)) printf("err : %i\n", err);
| ^~~
untitled1.c:16:57: note: each undeclared identifier is reported only once for each function it appears in
untitled1.c:18:18: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘__syscall_slong_t’ {aka ‘long int’} [-Wformat=]
18 | printf("%d microsecs %d\n",(endx.tv_nsec-startx.tv_nsec)/1000, endx.tv_sec-startx.tv_sec);
| ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| int __syscall_slong_t {aka long int}
| %ld
untitled1.c:18:31: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘__time_t’ {aka ‘long int’} [-Wformat=]
18 | printf("%d microsecs %d\n",(endx.tv_nsec-startx.tv_nsec)/1000, endx.tv_sec-startx.tv_sec);
| ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| int __time_t {aka long int}
| %ld
Compilation failed.
When compiling, always enable the warnings, then fix those warnings.
to start, suggest casting the result of the call to time() to be a long int
as to your question:
context switches take time AND the cpu(s) are probably busy with other tasks AND the task scheduler only looks at the list of tasks ready to run periodically , so your request will not be immediately serviced.
to obtain a more accurate timing, do not depend on the OS. Rather use one of the hardware timers to produce a interrupt event when you want the elapsed time to expire. Then use an interrupt handler to handle the interrupt event from the hardware timer.
#include <windows.h>
BOOL MyCtrlHandler(DWORD ctrlType) {
return TRUE;
}
int main(void) {
SetConsoleCtrlHandler(MyCtrlHandler, TRUE);
return 0;
}
The function signature matches the doc:
The PHANDLER_ROUTINE type defines a pointer to this callback function. HandlerRoutine is a placeholder for the application-defined function name.
If I cross-compile it with MinGW in 64 bits, it works:
$ x86_64-w64-mingw32-gcc ctrl.c
$
But in 32 bits, I get a warning:
$ i686-w64-mingw32-gcc ctrl.c
ctrl.c: In function ‘main’:
ctrl.c:8:27: warning: passing argument 1 of ‘SetConsoleCtrlHandler’ from incompatible pointer type [-Wincompatible-pointer-types]
8 | SetConsoleCtrlHandler(MyCtrlHandler, TRUE);
| ^~~~~~~~~~~~~
| |
| BOOL (*)(DWORD) {aka int (*)(long unsigned int)}
In file included from /usr/share/mingw-w64/include/windows.h:74,
from ctrl.c:1:
/usr/share/mingw-w64/include/wincon.h:249:68: note: expected ‘PHANDLER_ROUTINE’ but argument is of type ‘BOOL (*)(DWORD)’ {aka ‘int (*)(long unsigned int)’}
249 | WINBASEAPI WINBOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine,WINBOOL Add);
|
$
I don't understand why, because MyCtrlHandler should have the same type as PHANDLER_ROUTINE.
The problem here is the difference between __cdecl and __stdcall. You must have lucked out with the default calling convention on your one successful attempt to compile. You need:
BOOL WINAPI MyCtrlHandler(DWORD ctrlType) {
return TRUE;
}