Skip to content

Instantly share code, notes, and snippets.

@jgcoded
Created June 26, 2015 21:08
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jgcoded/5469a4d06c60519693bc to your computer and use it in GitHub Desktop.
Save jgcoded/5469a4d06c60519693bc to your computer and use it in GitHub Desktop.
Using Windows Shared Memory in Unreal Engine because the Unreal Engine API for shared memory does not work on Windows.
// Fill out your copyright notice in the Description page of Project Settings.
#include "VTBGame.h"
#ifdef WIN32
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <memory>
#endif
#include "WindowsSharedMemory.h"
#define MUTEX_LOCK_TIMEOUT_MS 100
WindowsSharedMemory::WindowsSharedMemory()
: SharedMemoryHandle(nullptr),
SharedMemoryMutex(nullptr),
SharedMemoryData(nullptr),
SharedMemorySize(0)
{
}
WindowsSharedMemory::~WindowsSharedMemory()
{
}
bool WindowsSharedMemory::CreateMappedMemory(const FString& sharedMemoryName, size_t size)
{
#ifdef WIN32
/* Create a named mutex for inter-process protection of data */
FString mutexName = sharedMemoryName + "MUTEX";
SharedMemoryMutex = CreateMutex(NULL, false, *mutexName);
if (SharedMemoryMutex == nullptr)
{
return false;
}
SharedMemorySize = size;
SharedMemoryHandle = CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
SharedMemorySize,
*sharedMemoryName);
int memExists = GetLastError();
if (memExists == ERROR_ALREADY_EXISTS || SharedMemoryHandle == nullptr)
{
CloseSharedMemory();
return false;
}
SharedMemoryData = (unsigned char *)MapViewOfFile(SharedMemoryHandle,
FILE_MAP_ALL_ACCESS,
0, 0,
SharedMemorySize);
if (!SharedMemoryData)
{
CloseSharedMemory();
return false;
}
LockMutex();
std::memset(SharedMemoryData, 0, SharedMemorySize);
UnlockMutex();
return true;
#else
return false;
#endif
}
bool WindowsSharedMemory::LockMutex()
{
#ifdef WIN32
if (SharedMemoryMutex)
{
DWORD32 result = WaitForSingleObject(SharedMemoryMutex, MUTEX_LOCK_TIMEOUT_MS);
if (result == WAIT_TIMEOUT)
{
UE_LOG(LogClass, Log, TEXT("MMI - VideoCapture Lock mutex timeout"));
return false;
}
}
return true;
#endif
}
void WindowsSharedMemory::WriteVideoCaptureImage(void* Meta, size_t MetaSize, const TArray<FColor>& PixelData)
{
#ifdef WIN32
int32 dataSize = PixelData.Num()*PixelData.GetTypeSize();
if (MetaSize + dataSize > SharedMemorySize)
return;
if (SharedMemoryMutex && SharedMemoryData && LockMutex())
{
std::memcpy(SharedMemoryData, Meta, MetaSize);
std::memcpy(SharedMemoryData + MetaSize, PixelData.GetData(), dataSize);
UnlockMutex();
}
#endif
}
void WindowsSharedMemory::UnlockMutex()
{
#ifdef WIN32
if (SharedMemoryMutex)
{
ReleaseMutex(SharedMemoryMutex);
}
#endif
}
void WindowsSharedMemory::CloseSharedMemory()
{
#ifdef WIN32
if (SharedMemoryMutex != nullptr)
{
ReleaseMutex(SharedMemoryMutex);
CloseHandle(SharedMemoryMutex);
SharedMemoryMutex = nullptr;
}
if (SharedMemoryData != nullptr)
{
UnmapViewOfFile(SharedMemoryData);
SharedMemoryData = nullptr;
}
if (SharedMemoryHandle != nullptr)
{
CloseHandle(SharedMemoryHandle);
SharedMemoryHandle = nullptr;
}
#endif
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "UnrealString.h"
#include "Color.h"
/**
* A single-purpose class used to write image data from a VideoCaptureComponent
* to shared memory on Windows.
*
* Unreal Engine does provide a cross-platform shared memory implementation,
* but that isn't working correctly. See this post on the AnswerHub for more info:
*
* https://answers.unrealengine.com/questions/228632/bug-fwindowsplatformmemory-fails-if-statements-in.html
*/
class YOURGAME_API WindowsSharedMemory
{
public:
WindowsSharedMemory();
~WindowsSharedMemory();
bool CreateMappedMemory(const FString& sharedMemoryName, size_t size);
void WriteVideoCaptureImage(void* Meta, size_t MetaSize, const TArray<FColor>& PixelData);
void CloseSharedMemory();
private:
bool LockMutex();
void UnlockMutex();
void* SharedMemoryHandle; ///< Mapped memory handle.
unsigned char* SharedMemoryData; ///< Pointer to memory data.
size_t SharedMemorySize; ///< Length of the memory (memory size).
void* SharedMemoryMutex; ///< Mutex handle.
};
@thecountif
Copy link

ERROR at #include "VTBGame.h"
May I ask you to demonstrate how to integrate the module to unreal engine

@aylum123
Copy link

When including windows.h I had some compile errors which looked like this: winioctl.h(10362): [C4668] '_WIN32_WINNT_WIN10_TH2' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'

Added #define WIN32_LEAN_AND_MEAN and it compiles now

@KaikoKan
Copy link

hi, how to use it and where i have to put it?

@aylum
Copy link

aylum commented Apr 19, 2023

Hello. Create new project, choose c++ (not blueprint project), in the project add new c++ class (actor or component). And paste parts of this code into your class. Also in .h file probably need to include #define WIN32_LEAN_AND_MEAN. To use it in ureal blueprint expose those functions with UFUNCTION(BlueprintCallable). Also you'll need visual studio with c++ stuff installed, and maybe also jet brains rider (switch default code editor in editor settings). Rider easyer for me, youtube/chatgpt for the help. There is also python script to read memory. Overall copy/paste some code into chatgpt, it will explain :)

Here is my ue 5.1.0 project. I'm not saying this is good, rather little messy :) I added new c++ component, and did creation/init in constructor, so later in blueprint I just use "write string to sharedmem" node. The code is in Source/camRec1/SharedMemoryComponent
https://drive.google.com/file/d/1EYp9gCmbglOZ298X6tG6Qtt2Y8WRD33A/view?usp=sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment