Edit: When only running on android, there is a simpler way. I have updated the answer below.
You'll have to pass a wrapper to the print function into the native code
void wrappedPrint(Pointer<Utf8> arg){
  print(Utf8.fromUtf8(arg));
}
typedef _wrappedPrint_C = Void Function(Pointer<Utf8> a);
final wrappedPrintPointer = Pointer.fromFunction<_wrappedPrint_C>(_wrappedPrint_C);
final void Function(Pointer) initialize =
  _nativeLibrary
    .lookup<NativeFunction<Void Function(Pointer)>>("initialize")
    .asFunction<void Function(Pointer)>();
initialize(wrappedPrintPointer);
and then use that in your C library:
void (*print)(char *);
void initialize(void (*printCallback)(char *)) {
    print = printCallback;
    print("C library initialized");
}
void someOtherFunction() {
    print("Hello World");
}
When only running on android, things get simpler. Instead of all of the above, do:
Simply use the android logging mechanism, it will show up on the console, at least when using flutter run. I'm assuming flutter attaches to logcat using the app's PID.
To do so, update the CMakeLists.txt with: 
find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib
              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       <your-libs-name-here>
                       # Links the log library to the target library.
                       ${log-lib} )
and in your c lib do:
#include <android/log.h>
void someOtherFunction() {
      __android_log_print(ANDROID_LOG_DEBUG, "flutter", "Hello world! You can use %s", "formatting");
}