Reputation: 13
I'm programming the stm32g071rb nucleo with Eclipse/gcc/ac6/sw4stm32 and I'm having some difficulty retargetting printf with a custom callback which prints to a SPI-connected display.
For now, my main looks something like this:
void main(void)
{
/* Declare BOARD typedef. */
BOARD_TypeDef_t board;
/* Initialize BOARD typedef. */
board_init(&board);
/* Initialize display */
display_init(&board.display[displayA]);
/* Writes a "B" to the display */
display_write(&board.display[displayA], 0x42);
}
What I would like to do is to use my display_write function and the display destination in a retargetted printf.
The options I have seen are:
Using __io_putchar function: This is available to be externed from the syscalls.c file. However, the only parameter it takes is the character to be printed, so I'm not sure and don't think I can get my BOARD_TypeDef_t in there.
Using write function: This is available in the syscalls.c file. However, I would rather use this the canonical way via __io_putchar and not by directly editing the write function.
Using fopencookie: I think this is the way I would like to do this but I'm having some difficulty. I learned that I had to activate _GNU_SOURCE and include stdio.h, so I added this atop main:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h> // Needed for ssize_t, cookie_io_functions_t, etc
#endif /* _GNU_SOURCE */
However, I'm still getting an "unknown type name 'cookie_io_functions_t'" error although this struct is defined in the included stdio.h and other calls to types in this stdio.h are referenced just fine, e.g., cookie_write_function_t, cookie_seek_function_t, etc.
I can't quite tell if this is per se a gcc issue or an Eclipse issue so progress has been slow.
Any suggestions on what I might do to clear this up are appreciated.
Upvotes: 0
Views: 1052
Reputation: 1
I got the printf retargetted on USB CDC VCOM Port adding __io_putchar to main.c - Following Code
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
int __io_putchar(int ch);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
setvbuf(stdout, NULL, _IONBF, 0);
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE B EGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(5000);
// CDC_Transmit_HS("Hello World", strlen("Hello World"));
printf("Hello World");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 120;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 5;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV4;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV8;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, NCS_MEMS_SPI_Pin|CSX_Pin|OTG_FS_PSO_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(ACP_RST_GPIO_Port, ACP_RST_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, RDX_Pin|WRX_DCX_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, LD3_Pin|LD4_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : A0_Pin A1_Pin A2_Pin A3_Pin
A4_Pin A5_Pin SDNRAS_Pin A6_Pin
A7_Pin A8_Pin A9_Pin */
GPIO_InitStruct.Pin = A0_Pin|A1_Pin|A2_Pin|A3_Pin
|A4_Pin|A5_Pin|SDNRAS_Pin|A6_Pin
|A7_Pin|A8_Pin|A9_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pins : SPI5_SCK_Pin SPI5_MISO_Pin SPI5_MOSI_Pin */
GPIO_InitStruct.Pin = SPI5_SCK_Pin|SPI5_MISO_Pin|SPI5_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/*Configure GPIO pin : ENABLE_Pin */
GPIO_InitStruct.Pin = ENABLE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(ENABLE_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : SDNWE_Pin */
GPIO_InitStruct.Pin = SDNWE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(SDNWE_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : NCS_MEMS_SPI_Pin CSX_Pin OTG_FS_PSO_Pin */
GPIO_InitStruct.Pin = NCS_MEMS_SPI_Pin|CSX_Pin|OTG_FS_PSO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : B1_Pin MEMS_INT1_Pin MEMS_INT2_Pin TP_INT1_Pin */
GPIO_InitStruct.Pin = B1_Pin|MEMS_INT1_Pin|MEMS_INT2_Pin|TP_INT1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : B5_Pin VSYNC_Pin G2_Pin R4_Pin
R5_Pin */
GPIO_InitStruct.Pin = B5_Pin|VSYNC_Pin|G2_Pin|R4_Pin
|R5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : ACP_RST_Pin */
GPIO_InitStruct.Pin = ACP_RST_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(ACP_RST_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : OTG_FS_OC_Pin */
GPIO_InitStruct.Pin = OTG_FS_OC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(OTG_FS_OC_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : R3_Pin R6_Pin */
GPIO_InitStruct.Pin = R3_Pin|R6_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_LTDC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : BOOT1_Pin */
GPIO_InitStruct.Pin = BOOT1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(BOOT1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : A10_Pin A11_Pin BA0_Pin BA1_Pin
SDCLK_Pin SDNCAS_Pin */
GPIO_InitStruct.Pin = A10_Pin|A11_Pin|BA0_Pin|BA1_Pin
|SDCLK_Pin|SDNCAS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : D4_Pin D5_Pin D6_Pin D7_Pin
D8_Pin D9_Pin D10_Pin D11_Pin
D12_Pin NBL0_Pin NBL1_Pin */
GPIO_InitStruct.Pin = D4_Pin|D5_Pin|D6_Pin|D7_Pin
|D8_Pin|D9_Pin|D10_Pin|D11_Pin
|D12_Pin|NBL0_Pin|NBL1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pins : G4_Pin G5_Pin B6_Pin B7_Pin */
GPIO_InitStruct.Pin = G4_Pin|G5_Pin|B6_Pin|B7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pins : D13_Pin D14_Pin D15_Pin D0_Pin
D1_Pin D2_Pin D3_Pin */
GPIO_InitStruct.Pin = D13_Pin|D14_Pin|D15_Pin|D0_Pin
|D1_Pin|D2_Pin|D3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : TE_Pin */
GPIO_InitStruct.Pin = TE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TE_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : RDX_Pin WRX_DCX_Pin */
GPIO_InitStruct.Pin = RDX_Pin|WRX_DCX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : R7_Pin DOTCLK_Pin B3_Pin */
GPIO_InitStruct.Pin = R7_Pin|DOTCLK_Pin|B3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : HSYNC_Pin G6_Pin R2_Pin */
GPIO_InitStruct.Pin = HSYNC_Pin|G6_Pin|R2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : I2C3_SDA_Pin */
GPIO_InitStruct.Pin = I2C3_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(I2C3_SDA_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : I2C3_SCL_Pin */
GPIO_InitStruct.Pin = I2C3_SCL_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(I2C3_SCL_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : STLINK_RX_Pin STLINK_TX_Pin */
GPIO_InitStruct.Pin = STLINK_RX_Pin|STLINK_TX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : G7_Pin B2_Pin */
GPIO_InitStruct.Pin = G7_Pin|B2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_LTDC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : G3_Pin B4_Pin */
GPIO_InitStruct.Pin = G3_Pin|B4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_LTDC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : LD3_Pin LD4_Pin */
GPIO_InitStruct.Pin = LD3_Pin|LD4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pins : SDCKE1_Pin SDNE1_Pin */
GPIO_InitStruct.Pin = SDCKE1_Pin|SDNE1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
int __io_putchar(int ch) {
CDC_Transmit_HS(&ch, 1);
return ch;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Upvotes: 0
Reputation: 13
After a bit of investigating, I found a workable solution.
The full post is here, including an image of the final product: https://zfembedded.wordpress.com/2020/02/27/redirecting-printf-on-stm32-using-fopencookie/
Starting with the basic program that prints a "B" to the screen, I did the following:
`
/* 2 */
#define _GNU_SOURCE
/* 1 */
#include <stdio.h>
/* 5 */
static ssize_t dummy_cookie_write(void *c, const char *buf, size_t size)
{
return size;
}
/* 6 */
int displayA_stream_write(struct _reent *q1, void *q2, const char *q3, int q4)
{
(void)q1;
BOARD_TypeDef_t* q5 = (BOARD_TypeDef_t*)q2;
int DataIdx;
for (DataIdx = 0; DataIdx < q4; DataIdx++)
{
display_write(&q5->display[displayA], *q3++);
}
return q4;
}
void main(void)
{
/* Declare BOARD typedef. */
BOARD_TypeDef_t board;
/* Initialize BOARD typedef. */
board_init(&board);
/* Initialize display */
display_init(&board.display[displayA]);
/* Writes a "B" to the display */
display_write(&board.display[displayA], 0x42);
/* 4 */
cookie_io_functions_t dummy_cookie_funcs = {
.read = 0,
.write = dummy_cookie_write, /* Setting this to 0 breaks the solution. */
.seek = 0,
.close = 0
};
/* 3 */
FILE *my_stream0 = fopencookie(NULL,"w", dummy_cookie_funcs); /* Replacing dummy_cookie_funcs with NULL breaks the solution. */
stdout = fopencookie(NULL,"w", dummy_cookie_funcs);
/* 8 */
setbuf(my_stream0, NULL);
setbuf(stdout, NULL);
/* 7 */
my_stream0->_write = displayA_stream_write;
my_stream0->_cookie = (void *)&board;
stdout->_write = displayA_stream_write;
stdout->_cookie = (void *)&board;
/* 9 */
fprintf(my_stream0, "\nNowhere");
fprintf(stdout, "\nSomewhere");
printf("\nHere");
}
`
The key find that made this all possible was finding out that #7 write was more important than #4 write.
Thanks for your suggestions.
Upvotes: 1