Win32: no_std, no_main, no libc?

When coding little windows console programs I try to avoid to C-Runtime.
I just use the Win32 API to get small, statically linked programms.
Often a few kilobytes in size. for example:

Very little sample. Just returing error code 99 from the little EXE (no_CRT.c):

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used 
#define STRICT
#include <windows.h>

void mainCRTStartup(void){

compile and link with:
cl.exe no_CRT.c /link /subsystem:console /NODEFAULTLIB kernel32.lib

Now I read about #![no_std], #![no_main] and wonder if I can do that same with Rust.
Also using the winapi crate as the documentation says:

By default the std feature of winapi is disabled, allowing you to write Windows applications using nothing but core and winapi.

And also not using any C-Runtime!
So after a few days of fiddling around I’m still out of luck with this piece of code:

#![windows_subsystem = "console"]

use core::panic::PanicInfo;

pub extern "system" fn mainCRTStartup()  {
    unsafe { winapi::um::processthreadsapi::ExitProcess(99); }
#[panic_handler]            #[no_mangle] pub extern "C" fn panic(_info: &PanicInfo) -> ! { loop {} }
#[lang = "eh_personality"]  #[no_mangle] pub extern "C" fn eh_personality() {}

cargo.toml looks like this:

name = "bee_no_std"
version = "0.1.0"
edition = "2018"
panic = "abort"
panic = "abort"
winapi = "0.3"

building with cargo +nightly build gives me:

error[E0601]: `main` function not found in crate `bee_no_std`
  = note: consider adding a `main` function to `src\`

Hope someone can enlighten me. :slight_smile:
Thank you very much for your help!

It might be worth reading A freestanding Rust binary.

The minimal example from that link goes something like this. First add panic=“abort” to your Cargo.toml

name = "nostd"
version = "0.1.0"
authors = ["THE AUTHOR"]
edition = "2018"

panic = "abort"

panic = "abort"

Then your main should look like this:

#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

#[no_mangle] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
    // this function is the entry point, since the linker looks for a function
    // named `_start` by default
    loop {}

/// This function is called on panic.
fn panic(_info: &PanicInfo) -> ! {
    loop {}

And you’d compile it using rustc more directly.

cargo rustc -- -C link-args="/ENTRY:_start /SUBSYSTEM:console"

And run it using:

1 Like

Thank you for your help!
In the meantime I found what was wrong.
Just by try and error. :slight_smile:

In there was the line


to “import” the ExitProcess() API from the winapi crate.
So I thought.

But this gaves me the error:

main function not found in crate bee_no_std

I deleted this line in and added the following to cargo.toml:

winapi = { version = "0.3.7", features = ["processthreadsapi"] }

Turn out! Working! After days!! :slight_smile:

Working sample:


you know that the Rust forum accepts markdown?

The important part is the syntax highlighting. :hugs:

Thanks you for the link!
I’m an old man. :slight_smile:
I’ll try my best next time. :wave:

Why don’t you edit your first post? :wink: Other people will read it and you can help them understand it properly by formatting the code. Please edit it :heart:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.