When using SDL2 on ios, SDL renames the main() function written by me to SDL_main, or I write a SDL_main function directly. And then SDL uses its own main function, as the real entry point. But in my use case I would like to retain control on the real entry point, i.e. the program starts from my main function instead of SDL's. Is there a config to disable SDL mangling my main function? Furthermore, after re-gaining control on the entry point, what is the necessary steps to prepare the necessary stuff for SDL to run correctly?
Related
In WIN32:
I'm sure that if the handle is the same, the memory may not be the same, and the same handle will be returned no matter how many times getMemoryWin32HandleKHR is executed.
This is consistent with vulkan's official explanation: Vulkan shares memory.
It doesn't seem to work properly in Linux.
In my program,
getMemoryWin32HandleKHR works normally and can return a different handle for each different memory.
The same memory returns the same handle.
But in getMemoryFdKHR, different memories return the same fd.
Or the same memory executes getMemoryFdKHR twice, it can return two different handles.
This causes me to fail the device memory allocation during subsequent imports.
I don't understand why this is?
Thanks!
#ifdef WIN32
texGl.handle = device.getMemoryWin32HandleKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 });
#else
VkDeviceMemory memory=VkDeviceMemory(info.memory);
int file_descriptor=-1;
VkMemoryGetFdInfoKHR get_fd_info{
VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, nullptr, memory,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
};
VkResult result= vkGetMemoryFdKHR(device,&get_fd_info,&file_descriptor);
assert(result==VK_SUCCESS);
texGl.handle=file_descriptor;
// texGl.handle = device.getMemoryFdKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd });
Win32 is nomal.
Linux is bad.
It will return VK_ERROR_OUT_OF_DEVICE_MEMORY.
#ifdef _WIN32
VkImportMemoryWin32HandleInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, sharedHandle, nullptr };
#elif __linux__
VkImportMemoryFdInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
sharedHandle};
#endif
VkMemoryAllocateInfo allocate_info{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
&import_allocate_info, // pNext
aligned_data_size_, // allocationSize
memory_index };
VkDeviceMemory device_memory=VK_NULL_HANDLE;
VkResult result = vkAllocateMemory(m_device, &allocate_info, nullptr, &device_memory);
NVVK_CHECK(result);
I think it has something to do with fd.
In my some test: if I try to get fd twice. use the next fd that vkAllocateMemory is work current......but I think is error .
The fd obtained in this way is different from the previous one.
Because each acquisition will be a different fd.
This makes it impossible for me to distinguish, and the following fd does vkAllocateMemory.
Still get an error.
So this test cannot be used.
I still think it should have the same process as win32. When the fd is obtained for the first time, vkAllocateMemory can be performed correctly.
thanks very much!
The Vulkan specifications for the Win32 handle and POSIX file descriptor interfaces explicitly state different things about their importing behavior.
For HANDLEs:
Importing memory object payloads from Windows handles does not transfer ownership of the handle to the Vulkan implementation. For handle types defined as NT handles, the application must release handle ownership using the CloseHandle system call when the handle is no longer needed.
For FDs:
Importing memory from a file descriptor transfers ownership of the file descriptor from the application to the Vulkan implementation. The application must not perform any operations on the file descriptor after a successful import.
So HANDLE importation leaves the HANLDE in a valid state, still referencing the memory object. File descriptor importation claims ownership of the FD, leaving it in a place where you cannot use it.
What this means is that the FD may have been released by the internal implementation. If that is the case, later calls to create a new FD may use the same FD index as a previous call.
The safest way to use both of these APIs is to have the Win32 version emulate the functionality of the FD version. Don't try to do any kinds of comparisons of handles. If you need some kind of comparison logic, then you'll have to implement it yourself. When you import a HANDLE, close it immediately afterwards.
I am working on exposing an audio library (C library) for Dart. To trigger the audio engine, it requires a few initializations steps (non blocking for UI), then audio processing is triggered with a perform function, which is blocking (audio processing is a heavy task). That is why I came to read about Dart isolates.
My first thought was that I only needed to call the performance method in the isolate, but it doesn't seem possible, since the perform function takes the engine state as first argument - this engine state is an opaque pointer ( Pointer in dart:ffi ). When trying to pass engine state to a new isolate with compute function, Dart VM returns an error - it cannot pass C pointers to an isolate.
I could not find a way to pass this data to the isolate, I assume this is due to the separate memory of main isolate and the one I'm creating.
So, I should probably manage the entire engine state in the isolate which means :
Create the engine state
Initialize it with some options (strings)
trigger the perform function
control audio at runtime
I couldn't find any example on how to perform this actions in the isolate, but triggered from main thread/isolate. Neither on how to manage isolate memory (keep the engine state, and use it). Of course I could do
Here is a non-isolated example of what I want to do :
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parametersString);
startEngine(engineState);
perform(engineState);
And at runtime, triggered by UI actions (like slider value changed, or button clicked) :
setEngineControl(engineState, valueToSet);
double controleValue = getEngineControl(engineState);
The engine state could be encapsulated in a class, I don't think it really matters here.
Whether it is a class or an opaque datatype, I can't find how to manage and keep this state, and perform triggers from main thread (processed in isolate). Any idea ?
In advance, thanks.
PS: I notice, while writing, that my question/explaination may not be precise, I have to say I'm a bit lost here, since I never used Dart Isolates. Please tell me if some information is missing.
EDIT April 24th :
It seems to be working with creating and managing object state inside the Isolate. But the main problem isn't solved. Because the perform method is actually blocking while it is not completed, there is no way to still receive messages in the isolate.
An option I thought first was to use the performBlock method, which only performs a block of audio samples. Like this :
while(performBlock(engineState)) {
// listen messages, and do something
}
But this doesn't seem to work, process is still blocked until audio performance finishes. Even if this loop is called in an async method in the isolate, it blocks, and no message are read.
I now think about the possibility to pass the Pointer<Void> managed in main isolate to another, that would then be the worker (for perform method only), and then be able to trigger some control methods from main isolate.
The isolate Dart package provides a registry sub library to manage some shared memory. But it is still impossible to pass void pointer between isolates.
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Invalid argument(s): Native objects (from dart:ffi) such as Pointers and Structs cannot be passed between isolates.
Has anyone already met this kind of situation ?
It is possible to get an address which this Pointer points to as a number and construct a new Pointer from this address (see Pointer.address and Pointer.fromAddress()). Since numbers can freely be passed between isolates, this can be used to pass native pointers between them.
In your case that could be done, for example, like this (I used Flutter's compute to make the example a bit simpler but that would apparently work with explicitly using Send/ReceivePorts as well)
// Callback to be used in a backround isolate.
// Returns address of the new engine.
int initEngine(String parameters) {
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parameters);
startEngine(engineState);
return engineState.address;
}
// Callback to be used in a backround isolate.
// Does whichever processing is needed using the given engine.
void processWithEngine(int engineStateAddress) {
final engineState = Pointer<Void>.fromAddress(engineStateAddress);
process(engineState);
}
void main() {
// Initialize the engine in a background isolate.
final address = compute(initEngine, "parameters");
final engineState = Pointer<Void>.fromAddress(address);
// Do some heavy computation in a background isolate using the engine.
compute(processWithEngine, engineState.address);
}
I ended up doing the processing of callbacks inside the audio loop itself.
while(performAudio())
{
tasks.forEach((String key, List<int> value) {
double val = getCallback(key);
value.forEach((int element) {
callbackPort.send([element, val]);
});
});
}
Where the 'val' is the thing you want to send to callback. The list of int 'value' is a list of callback index.
Let's say you audio loop performs with vector size of 512 samples, you will be able to pass your callbacks after every 512 audio samples are processed, which means 48000 / 512 times per second (assuming you sample rate is 48000). This method is not the best one but it works, I still have to see if it works in very intensive processing context though. Here, it has been thought for realtime audio, but it could work the same for audio rendering.
You can see the full code here : https://framagit.org/johannphilippe/csounddart/-/blob/master/lib/csoundnative.dart
My iOS app (using the Boehm garbage collector) was rejected in the AppStore because of one private API function call. Here the offending function in file os_dep.c:
/* These are not defined in any header, although they are documented */
extern boolean_t
exc_server(mach_msg_header_t *, mach_msg_header_t *);
Here the link to the file: os_dep.c on github
I tried to comment out both the function definition and call, and the app seems running fine, but that's a really bad hack.
My question: is this function call critical? Is it really needed in iOS?
The function is only needed in the incremental GC mode which is enabled by GC_enable_incremental() call. I suspect you don't call it, so exc_server() and friends aren't called in the app.
Instead of commenting out exc_server(), I'd recommend you to pass "-D GC_DISABLE_INCREMENTAL" which removes the incremental mode support from the collector binary.
We have a native C++ add-on running in an Electron renderer process providing Uint8Array bitmap data to JavaScript where it is painted into a canvas via textImage2D in a webgl context or putImageData in a 2d context.
The Uint8Array is allocated in the native addon and passed via a callback to JS. It is not deallocated immediately after the callback ends, and is kept in a memory pool that holds the last 10 frames sent to be available for async painting.
If the array is passed as is to putImageData or texImage2D, the renderer completely freezes. If it is copied into a new TypedArray beforehand, there is no problem, but we would like to avoid the extra copy operation, hence the memory pool.
I have a feeling the freezing is related to the way Chromium handles GL commands via it's command buffer.
I've tried the following Chromimum command line args in an attempt to isolate the issue, with no luck - renderer process is frozen when the array is not copied beforehand):
--use-passthrough-cmd-decoder results in longer render times for 2d, and a null context for webgl
--disable-gpu-sandbox does nothing
--in-process-gpu does nothing
Any idea what is happening?
I want to know how can I get a keyboard input in contiki os.
I already tried getchar(),getch(),scanf(),gets() and none worked, so I want to know if somebody can help me.
getchar,getch,scanf,gets are sort of POSIX things that read from files (e.g. stdin) --- these don't exist in Contiki (all though you could probably use them with the native platform).
So the first question to ask is what platform are you using and what do you mean by "keyboard". If keyboard means typing characters that are sent via a serial port from a computer then you have to know where they are received on the thing running Contiki. A typical arrangement is to receive characters on a uart, say, uart1.
In this case, contiki uses a callback such as uart1_input_handler that will be defined by the application. Platform main loops will check if there are characters to send to the input_handler and then check that an input_handler is defined. If so, will call something like uart1_input_handler(c).
You can see this code for the various platforms by grepping for uart1_input_handler:
platform/redbee-econotag/contiki-mc1322x-main.c: uart1_input_handler(uart1_getc());
cpu/msp430/dev/uart1x.c: if(uart1_input_handler(c)) {
cpu/stm32w108/dev/uart1.c: uart1_input_handler(c);
etc...
Some examples that register an input handler and process the characters:
example/shell:
/* set up the shell */
uart1_set_input(serial_line_input_byte);
serial_line_init();
serial_shell_init();
slip, in examples/ipv6/rpl-border-router/slip-bridge.c
slip_set_input_callback(slip_input_callback);
My guess for what you want to do would be to start with the shell examples and try to get those working.
The example cited below is from the Wiki pages of contiki on github. It demonstrates how the contiki specific mechanism for serial input works. Like mariano mentioned above that a callback has to be defined for the serial drivers specific to the platform you are using. I have used for ex. "rs232_set_input(RS232_PORT_0, serial_line_input_byte) ; " for my atmega128 MCU. The serial i/o drivers use this callback mechanism to post input characters to the "serial_line_process" defined in serial-line.c file. This process then broadcasts the serial_line_event_message to all processes along with the data read on the serial line. A process like the eg. stated below, can catch this event and process the input as per the requirements.
The callback mentioned above is defined in $(CONTIKI)/core/dev/serial-line.c. Check that out.
Once you initialise it using serial_line_init(), you are good to go.
#include "contiki.h"
#include "dev/serial-line.h"
#include <stdio.h>
PROCESS(test_serial, "Serial line test process");
AUTOSTART_PROCESSES(&test_serial);
PROCESS_THREAD(test_serial, ev, data)
{
PROCESS_BEGIN();
for(;;) {
PROCESS_YIELD();
if(ev == serial_line_event_message) {
printf("received line: %s\n", (char *)data);
}
}
PROCESS_END();
}
I assume you use COOJA (or maybe you connected a keyboard to your device so my answer will not be correct).
COOJA is an emulator, not a simulator.
If you want a responsive design, use the sensor button (on sky platform for example)
SENSORS_ACTIVATE(button_sensor);
/* Wait until we get a sensor event with the button sensor as data. */
PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event &&
data == &button_sensor);
Hope it helped.