Getting 0xC000041D crash in simple directX12 application - crash

I have a simple Window class and I use a function for WM_PAINT that clears the render target view and presents the final image.so there's not much into it but I get a crash on line FLOAT clearColor[] = { 0.2f, 0.4f, 0.6f, 1.0f }; that says:0xC000041D: An unhandled exception was encountered during a user callback.
here's the window class:
class Win32Window : public WindowsWindow
{
public:
Win32Window(const WindowProps& props);
virtual ~Win32Window();
void OnUpdate() override;
unsigned int GetWidth() const override { return m_Data.Width; }
unsigned int GetHeight() const override { return m_Data.Height; }
void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
void SetVSync(bool enabled) override;
bool IsVSync() const override;
virtual void* GetNativeWindow() const override { return m_Window; }
private:
HWND m_Window;
RECT m_WindowRect;
HINSTANCE m_hInst;
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
virtual void Init(const WindowProps& props);
virtual void Shutdown();
};
the definitions:
Win32Window::Win32Window(const WindowProps& props)
{
HZ_PROFILE_FUNCTION();
Init(props);
}
Win32Window::~Win32Window()
{
HZ_PROFILE_FUNCTION();
Shutdown();
}
void Win32Window::Init(const WindowProps& props)
{
m_hInst = GetModuleHandle(0);
m_Data.WideCharacterTitle = props.WideCharacterTitle;
m_Data.Width = props.Width;
m_Data.Height = props.Height;
HZ_CORE_INFO("Creating window {0} ({1}, {2})",props.StringTypeTitle, props.Width, props.Height);
WNDCLASSEXW windowClass = {};
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = &WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = m_hInst;
windowClass.hIcon = ::LoadIcon(m_hInst, NULL);
windowClass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = m_Data.WideCharacterTitle;
windowClass.hIconSm = ::LoadIcon(m_hInst, NULL);
static ATOM atom = ::RegisterClassExW(&windowClass);
assert(atom > 0);
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
RECT windowRect = { 0, 0, static_cast<LONG>(m_Data.Width), static_cast<LONG>(m_Data.Height) };
::AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);
int windowWidth = windowRect.right - windowRect.left;
int windowHeight = windowRect.bottom - windowRect.top;
int windowX = std::max<int>(0, (screenWidth - windowWidth) / 2);
int windowY = std::max<int>(0, (screenHeight - windowHeight) / 2);
m_Window = ::CreateWindowExW(NULL, m_Data.WideCharacterTitle, m_Data.WideCharacterTitle, WS_OVERLAPPEDWINDOW, windowX, windowY, windowWidth, windowHeight, NULL, NULL, m_hInst, this);
assert(m_Window && "Failed to create window");
m_Context = GraphicsContext::Create(m_Window);
m_Context->Init();
::ShowWindow(m_Window, SW_SHOW);
::UpdateWindow(m_Window);
}
LRESULT Win32Window::MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
m_Context->RenderWindow();
break;
case WM_DESTROY:
::PostQuitMessage(0);
break;
default:
return ::DefWindowProcW(hwnd, message, wParam, lParam);
}
}
LRESULT Win32Window::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Win32Window* instance;
if (message == WM_CREATE)
{
instance = (Win32Window*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
instance->m_Window = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)instance);
}
else
{
instance = (Win32Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (instance)
{
return instance->MainWndProc(hwnd, message, wParam, lParam);
}
return ::DefWindowProcW(hwnd, message, wParam, lParam);
}
void Win32Window::Shutdown()
{
DestroyWindow(m_Window);
m_Window = nullptr;
}
void Win32Window::OnUpdate()
{
m_Context->Update();
}
void Win32Window::SetVSync(bool enabled)
{
m_Data.VSync = enabled;
}
bool Win32Window::IsVSync() const
{
return m_Data.VSync;
}
m_Context is coming from the parent class, And also WindowProps that has some data for initializing the window .definition of m_Context->RenderWindow():
m_CommnadQueue = D3D12Core::Get().GetCommandQueue(D3D12_COMMAND_LIST_TYPE_DIRECT);
auto m_CommandList = m_CommnadQueue->GetCommandList();
m_CurrentBackBufferIndex = m_SwapChain->GetCurrentBackBufferIndex();
auto m_BackBuffer = D3D12Core::Get().m_BackBuffers[m_CurrentBackBufferIndex];
auto m_RTVDescriptorSize = D3D12Core::Get().GetDevice()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
{
CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_BackBuffer.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
m_CommandList->ResourceBarrier(1, &barrier);
FLOAT clearColor[] = { 0.2f, 0.4f, 0.6f, 1.0f };
CD3DX12_CPU_DESCRIPTOR_HANDLE rtv(m_RTVDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), m_CurrentBackBufferIndex, m_RTVDescriptorSize);
m_CommandList->ClearRenderTargetView(rtv, clearColor, 0, nullptr);
}
{
CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_BackBuffer.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
m_CommandList->ResourceBarrier(1, &barrier);
m_CommandList->Close();
ID3D12CommandList* const commandLists[] =
{
m_CommandList.Get()
};
D3D12Core::Get().m_FenceValues[m_CurrentBackBufferIndex] = m_CommnadQueue->ExecuteCommandList(m_CommandList);
UINT syncInterval = m_VSync;
UINT presentFlags = m_TearingSupport && !m_VSync ? DXGI_PRESENT_ALLOW_TEARING : 0;
m_SwapChain->Present(syncInterval, presentFlags);
m_CommnadQueue->WaitForFenceValue(D3D12Core::Get().m_FenceValues[m_CurrentBackBufferIndex]);
}
If there is anything else that I should put in question pls tell me.You can shout at me for my dumbness if you want to but help me pls,thx.
EDIT:
debug layer:
#ifdef _DEBUG
ComPtr<ID3D12Debug> debugInterface;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface))))
{
debugInterface->EnableDebugLayer();
}
#endif

WaitForFenceValue after every Present is an extremely slow way to render in DirectX 12. You should generally cue 2-3 frames to the GPU rather than forcing the GPU to stall every frame. It is also highly problematic to have your WndProc block, which is what happens here. Your WndProc should always complete quickly as many hundreds of messages are processed a second for most applications.
Usually Direct3D rendering is not done within WM_PAINT. For a number of examples of common render loops, see GitHub.

Related

Why does my screen starts blinking when I toggle the full screen state?

I'm trying to implement full screen support on my Direct3D11 application, but I've been having a issue with this. I'm using the ALT+ENTER key combination that makes the IDXGISwapChain change the target window to full screen and back. But when I go into full screen my back buffer starts blinking between the color that I have set on the call to ID3D11DeviceContext::ClearRenderTargetView to black.
I also have code in the WinProc function of my window, that when it receives the WM_SIZE message, this code is executed.
If I don't use this code to resize the buffers, the blinking doesn't happen for some reason.
If I call ID3D11DeviceContext::ClearRenderTargetView once after creating the new swap chain, and again after calling IDXGISwapChain::Present, the blinking also doesn't happen.
It's a bit confusing, but I have a theory that maybe, when I go to full screen mode and call IDXGISwapChain::ResizeBuffers it somehow makes my swap chain have more than one buffer, and when I call IDXGISwapChain::Present it rotates to the next buffer, which is on the default color black.
Note that I have also tried to call IDXGISwapChain::SetFullscreenState, but the issue persists.
My code is too big to paste here, so I took the code from this tutorial and changed it a bit to show the behaviour I'm describing:
#include <windows.h>
#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// global declarations
IDXGISwapChain* swapchain;
ID3D11Device* dev;
ID3D11DeviceContext* devcon;
ID3D11RenderTargetView* backbuffer;
void InitD3D(HWND hWnd);
void RenderFrame(void);
void CleanD3D(void);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int main()
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(nullptr);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
RECT wr = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
hWnd = CreateWindowEx(NULL,
L"WindowClass",
L"Our First Direct3D Program",
WS_OVERLAPPEDWINDOW,
300,
300,
wr.right - wr.left,
wr.bottom - wr.top,
NULL,
NULL,
GetModuleHandle(nullptr),
NULL);
ShowWindow(hWnd, SW_SHOW);
InitD3D(hWnd);
MSG msg;
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
RenderFrame();
}
CleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
case WM_SIZE: {
if (swapchain)
{
devcon->OMSetRenderTargets(0, 0, 0);
backbuffer->Release();
HRESULT hr;
hr = swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
ID3D11Texture2D* pBuffer;
hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D),
(void**)&pBuffer);
hr = dev->CreateRenderTargetView(pBuffer, NULL,
&backbuffer);
pBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
float fColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
devcon->ClearRenderTargetView(backbuffer, fColor);
DXGI_SWAP_CHAIN_DESC Desc;
ZeroMemory(&Desc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapchain->GetDesc(&Desc);
D3D11_VIEWPORT vp;
vp.Width = Desc.BufferDesc.Width;
vp.Height = Desc.BufferDesc.Height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
devcon->RSSetViewports(1, &vp);
}
return 1;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void InitD3D(HWND hWnd)
{
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.Width = SCREEN_WIDTH;
scd.BufferDesc.Height = SCREEN_HEIGHT;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hWnd;
scd.SampleDesc.Count = 1;
scd.Windowed = TRUE;
scd.Flags = 0;
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon);
ID3D11Texture2D* pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
float fColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
devcon->ClearRenderTargetView(backbuffer, fColor);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;
devcon->RSSetViewports(1, &viewport);
}
void RenderFrame(void)
{
swapchain->Present(1, 0);
}
void CleanD3D(void)
{
swapchain->SetFullscreenState(FALSE, NULL);
swapchain->Release();
backbuffer->Release();
dev->Release();
devcon->Release();
After messing a bit with the code, I've noticed that when the SampleDesc::Count variable from the DXGI_SWAP_CHAIN_DESC is not equal to 1, the blinking also doesn't happen.

Visual-C++ Win32 C++ Application. How do I print variables to the main screen?

I have tried C++11 methods and C methods to convert the string before printing and they either: Returned a string of the same characters or didn't print anything at all. I just wanted to know 3 things really: Is there a fault in the online tutorials and examples? Is there a fault in my interpretation and implementation of the code? What could I do differently to get this working?
// Yu-Gi-Oh! LP Calculator.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Yu-Gi-Oh! LP Calculator.h"
#define MAX_LOADSTRING 100
#define LP UINT
#define ID CHAR
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Global Life Point Variables
struct Player {
LP Lp;
ID Name[MAX_LOADSTRING];
};
struct Player1, Player2, Player3, Player4;
// Forward declarations of functions included in this code module:
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TEMP: Remove these initializations when preferences are implemented.
Player1.Lp = 8000;
Player2.Lp = 8000;
Player3.Lp = 8000;
Player4.Lp = 8000;
LoadStringA(hInstance, (UINT)"John\0", Player1.Name, MAX_LOADSTRING);
LoadStringA(hInstance, (UINT)"Phil\0", Player2.Name, MAX_LOADSTRING);
LoadStringA(hInstance, NULL, Player3.Name, MAX_LOADSTRING);
LoadStringA(hInstance, NULL, Player4.Name, MAX_LOADSTRING);
// END TEMP
// TODO: Place code here.
// TODO: Load preferences file.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_YUGIOHLPCALCULATOR, szWindowClass, MAX_LOADSTRING);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_YUGIOHLPCALCULATOR));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_YUGIOHLPCALCULATOR);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_YUGIOHLPCALCULATOR));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
GetClientRect(hWnd, &rect);
CHAR b[] = { NULL };
sprintf((char* const)&b, "%s", Player1.Name);
DrawTextA(hdc, b, ARRAYSIZE(b), &rect, DT_SINGLELINE | DT_CENTER | DT_TOP);
//TextOutA(hdc, rect.left, rect.top, s, ARRAYSIZE(Player1.Name));
SelectClipPath(hdc, RGN_AND);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
By changing:
#define ID CHAR
to:
#define ID LPCSTR
and changing:
ID Name[MAX_LOADSTRING];
to:
ID Name;
I made Player1.Name compatible with the type of the 2nd parameter of the DrawTextA function.
I then changed the 3rd parameter to -1 instead of using ARRAYSIZE(). This means that the function checks the size of the string itself? So the function is called like this:
DrawTextA(hdc, Player1.Name, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_TOP);
All I needed to do then was Initialize the string with my values instead of using LoadStringA so I changed:
LoadStringA(hInstance, (UINT)"John\0", Player1.Name, MAX_LOADSTRING);
to:
Player1.Name = "John";

Member modified by method reverts after it exits

I have a window (Windows), and my wndProc is basically the same as the one on the windows guides. However, even though WM_CLOSE gets passed (and I can use if(msg == WM_CLOSE)), I can't seem to set my shouldClose flag. I've confirmed that I still get the event within my processMessage method. So my question is this: what is going on, and how can I make it work?
Edit: I tried storing the window data as a struct instead of a class, and everything works just fine. Ie. All I changed was the type of the class, and a few errors.
class Win32Window {
this(wstring title, int width, int height) {
immutable wstring className = "glass_def_class_name\0";
auto hInstance = GetModuleHandle(null);
WNDCLASSW wc;
wc.lpfnWndProc = &windowProc;
wc.hInstance = hInstance;
wc.lpszClassName = &className[0];
RegisterClassW(&wc);
handle = CreateWindowExW(
0,
&className[0],
&title[0],
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
null, null,
hInstance,
cast(void*) this);
ShowWindow(handle, SW_NORMAL);
}
~this() {
DestroyWindow(handle);
}
void processEvents() {
MSG msg;
while (PeekMessage(&msg, handle, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
bool shouldClose;
HWND handle;
private:
LRESULT processMessage(UINT msg, WPARAM wp, LPARAM lp) nothrow {
switch (msg) {
case WM_CLOSE:
shouldClose = true;
return 0;
default:
return DefWindowProc(handle, msg, wp, lp);
}
}
}
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_CREATE) {
CREATESTRUCT* create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
window = cast(Win32Window* ptr);
}
if (window)
return window.processMessage(msg, wp, lp);
else
return DefWindowProc(hwnd, msg, wp, lp);
}
void main()
{
auto window = new Win32Window("test", 1280, 720);
while(window.shouldClose == false) {
window.processEvents();
}
window.destroy();
}
Member modified by method reverts after it exits
this was when you worked with local copy of object, and make modification to this local copy, but not really to object. I not view another explanations
inside windowProc you do next Win32Window window = *(cast(Win32Window*) ptr); - so you make local copy of your initial object state in windowProc and then do all modification to this local copy - of course all it lost when you exit from windowProc correct code must be next:
private LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window* window;
if (msg == WM_NCCREATE) {
CREATESTRUCT* create = (CREATESTRUCT*) lp;
window = (Win32Window*) create.lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) create.lpCreateParams);
window.handle = hwnd;
}
else {
window = (Win32Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
return window ? window->processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
It turns out that you can't actually cast a pointer directly to a reference. An intermediary is necessary (or something to that effect). Thus, the winProc should look something like this:
private extern (Windows) LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) nothrow {
Win32Window window;
if (msg == WM_NCCREATE) {
auto create = cast(CREATESTRUCT*) lp;
window = cast(Win32Window) (cast(void*) create.lpCreateParams);
window.handle = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, cast(LONG_PTR) create.lpCreateParams);
}
else {
window = cast(Win32Window) (cast(void*) GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
return window ? window.processMessage(msg, wp, lp) : DefWindowProc(hwnd, msg, wp, lp);
}
Note the extra cast(void*) before create.lpCreateParams and GetWindowLongPtr(hwnd, GWLP_USERDATA). I'm not entirely sure why this works as opposed to my original code, but it seems to work, and I'll do some more investigating when I have the time.

PInvoke - Issue while calling DJVU function from C# code. Attempted to read or write protected memory

UPDATE 3-4-15:11IS
As recommended by David modified PInvoke as below, this time I am getting different error "Unhandled exception of type System.ExecutionEngineException occurred in mscorlib.dll"
[DllImport("C:\\Program Files\\DJVULIBRE\\LIBDJVULIBRE.dll", CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern int ddjvu_page_render(IntPtr page, ddjvu_render_mode_t mode, ref ddjvu_rect_t pagerect,
ref ddjvu_rect_t renderrect,
IntPtr pixelformat,
uint rowsize,
[Out][MarshalAs(UnmanagedType.LPArray)]byte[] imagebuffer);
Thanks David for your valuable time, I think is close to a fix.
HISTORY
I know there are many questions in this subject but none of them help to resolve the issue I am currently facing.
Below is the API function in C Language
DDJVUAPI int
ddjvu_page_render(ddjvu_page_t *page,
const ddjvu_render_mode_t mode,
const ddjvu_rect_t *pagerect,
const ddjvu_rect_t *renderrect,
const ddjvu_format_t *pixelformat,
unsigned long rowsize,
char *imagebuffer );
Below is the PInvoke signature of C Function added in .NET code
[DllImport("C:\\Program Files\\DJVULIBRE\\LIBDJVULIBRE.dll", CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern int ddjvu_page_render(IntPtr page, ddjvu_render_mode_t mode, IntPtr pagerect,
IntPtr renderrect,
IntPtr pixelformat,
ulong rowsize,
[Out][MarshalAs(UnmanagedType.LPArray)]byte[] imagebuffer);
Below is how I am calling this function in the c# code
byte* buffer = (byte *)Memory.Alloc(nSize);
try
{
IntPtr ptr1 = (IntPtr)Memory.Alloc(Marshal.SizeOf(prect));
Marshal.StructureToPtr(prect, ptr1, false);
IntPtr ptr2 = (IntPtr)Memory.Alloc(Marshal.SizeOf(rrect));
Marshal.StructureToPtr(rrect, ptr2, false);
byte[] array = new byte[nSize];
fixed (byte* p = array) Memory.Copy(buffer, p, nSize);
ddjvu_page_render(page, ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY, ptr1, ptr2, fmt, (ulong)stride, array);
}
finally
{
Memory.Free(buffer);
}
call to ddjvu_page_render in above code is throwing "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Prior to this post I must have tried all the option could find in various blogs.
Appreciate any help, is almost a day I am clueless, your timely help could save my job
UPDATE 3-4-15:7:44IS
This code is using DJVULibre
UPDATE 3-4-15:8:35IS
Here is the code I have in Form Load
ctx = ddjvu_context_create(System.AppDomain.CurrentDomain.FriendlyName);
if (ctx != null)
{
string djFile = "C:\\Users\\rammohan.chavakula\\Documents\\eiasample.djvu";
doc = ddjvu_document_create_by_filename(ctx, djFile, 100);
if (doc != null)
{
while (ddjvu_job_status(ddjvu_document_job(doc)) >= ddjvu_status_t.DDJVU_JOB_OK)
SpinDdjvuMessageLoop(ctx, true);
int pageCount = ddjvu_document_get_pagenum(doc);
mediaboxes = new Rectangle[pageCount];
for (int i = 0; i < pageCount; i++)
{
ddjvu_status_t status;
ddjvu_pageinfo_t info = new ddjvu_pageinfo_t();
while ((status = ddjvu_document_get_pageinfo_imp(doc, i, ref info, (uint)System.Runtime.InteropServices.Marshal.SizeOf(info))) < ddjvu_status_t.DDJVU_JOB_OK)
SpinDdjvuMessageLoop(ctx, true);
if (status != ddjvu_status_t.DDJVU_JOB_OK)
continue;
mediaboxes[i] = new Rectangle(0, 0, info.width / info.dpi,
info.height / info.dpi);
}
}
ddjvu_context_release(ctx);
}
In OnPaint function I have this below code
if (doc == null)
{
base.OnPaint(e);
return;
}
Rectangle pageRc = PageMediabox(1);
Rectangle screen = Transform(pageRc, 1, zoom, rotation, false);
Rectangle full = Transform(PageMediabox(1), 1, zoom, rotation, false);
full.Intersect(screen);
IntPtr page = ddjvu_page_create_by_pageno(doc, 1);
if (page == null )
{
base.OnPaint(e);
return;
}
int rotation4 = (((-rotation / 90) % 4) + 4) % 4;
ddjvu_page_set_rotation(page, (ddjvu_page_rotation_t)rotation4);
while (ddjvu_job_status(ddjvu_page_job(page)) >= ddjvu_status_t.DDJVU_JOB_OK)
SpinDdjvuMessageLoop(ctx, true);
if (ddjvu_job_status(ddjvu_page_job(page)) >= ddjvu_status_t.DDJVU_JOB_FAILED)
{
base.OnPaint(e);
return;
}
IntPtr fmt = ddjvu_format_create(ddjvu_format_style_t.DDJVU_FORMAT_BGR24, 0, (UIntPtr)null);
ddjvu_format_set_row_order(fmt, /* top_to_bottom */1);
ddjvu_rect_t prect = new ddjvu_rect_t(full.X, full.Y, (uint)full.Width, (uint)full.Height);
ddjvu_rect_t rrect = new ddjvu_rect_t(screen.X, 2 * full.Y + screen.Y + full.Height - screen.Height, (uint)screen.Width, (uint)screen.Height);
int stride = ((screen.Width * 3 + 3) / 4) * 4;
//byte tmp;
////ScopedMem<char> bmpData(SAZA(char, stride * (screen.dy + 5)));
//for (int y = 0; y < rrect.h; y++) {
// int step_y = y * SCREEN_WIDTH;
// for (int x=0; x < rrect.w; x++) {
// tmp = (byte)((imagebuf[x + step_y] >> 5) << 5);
// }
//}
int rowsize = mediaboxes[0].Width * 3;
int nSize = rowsize * (mediaboxes[0].Height) * 10;
unsafe
{
byte* buffer = (byte *)Memory.Alloc(nSize);
try
{
IntPtr ptr1 = (IntPtr)Memory.Alloc(Marshal.SizeOf(prect));
Marshal.StructureToPtr(prect, ptr1, false);
IntPtr ptr2 = (IntPtr)Memory.Alloc(Marshal.SizeOf(rrect));
Marshal.StructureToPtr(rrect, ptr2, false);
byte[] array = new byte[nSize];
fixed (byte* p = array) Memory.Copy(buffer, p, nSize);
ddjvu_page_render(page, ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY, ptr1, ptr2, fmt, (ulong)stride, array);
}
finally
{
Memory.Free(buffer);
}
ddjvu_page_render should return arbitrary data of page which is to be rendered in a given rectangle area. Once after that I should be able to create image from arbitrary data & display in the screen
Here's how I would write the p/invoke:
[DllImport(dllname, CharSet=CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern int ddjvu_page_render(
[In] IntPtr page,
[In] ddjvu_render_mode_t mode,
[In] ref ddjvu_rect_t pagerect,
[In] ref ddjvu_rect_t renderrect,
[In] ref ddjvu_format_t pixelformat,
[In] uint rowsize,
[Out] byte[] imagebuffer
);
Note that I've stopped using unsafe, and am letting the marshaler handle the structs automatically.
There are quite a few assumptions here that I cannot verify:
The calling convention. It might not be cdecl. The C++ header will would have the definitive answer.
The first parameter is a void* handle type, I presume.
ddjvu_render_mode_t is an enum that you have translated correctly.
The three ref parameters are structs, passed by reference. I cannot check that you have translated them correctly.
Calling this function would be something like this:
byte[] imagebuffer = new byte[nSize];
int retval = ddjvu_page_render(
page,
ddjvu_render_mode_t.DDJVU_RENDER_MASKONLY,
ref prect,
ref rrect,
ref fmt,
(uint)stride,
imagebuffer
);
if (retval != ??)
// handle error
This is quite a broad brush answer. I hope it points you in the right direction. I don't think that all your problems will be solved by this.

binding is used in WCF as a remoting alternative

If we want to replace remoting to WCF what biding is used ?
If we have used a shared dll beetwen two application in remoting to send message.
how this task can be done in WCF.
The answer would depend on your infrastructure. If your services are all on the same machine, you could use NetNamedPipeBinding. If services and consumers are on different machines, you could use either NetTcpBinding or BasicHttpBinding.
This solved my purpose...
private const int RF_TESTMESSAGE = 0xA123;
const int WM_USER = 0x0400;
const int WM_CUSTOM_MESSAGE = WM_USER + 0x0001;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int Msg, IntPtr wParam, int lParam);
public FormVideoApp()
{
InitializeComponent();
lblProcID.Text = string.Format("This process ID: {0}", Process.GetCurrentProcess().Id);
}
private void button1_Click(object sender, EventArgs e)
{
//get this running process
Process proc = Process.GetCurrentProcess();
//get all other (possible) running instances
//Process[] processes = Process.GetProcessesByName(proc.ProcessName);
Process[] processes = Process.GetProcessesByName("Application");
int numberToSend = 1500;
string str = string.Empty;
str = "start";
switch (str)
{
case "start":
numberToSend = 101;
break;
case "stop":
numberToSend = 102;
break;
case "error":
numberToSend = 103;
break;
}
if (processes.Length > 0)
{
//iterate through all running target applications
foreach (Process p in processes)
{
if (p.Id != proc.Id)
{
//now send the RF_TESTMESSAGE to the running instance
//SendMessage(p.MainWindowHandle, RF_TESTMESSAGE, IntPtr.Zero, IntPtr.Zero);
SendMessage(p.MainWindowHandle, WM_CUSTOM_MESSAGE, IntPtr.Zero, numberToSend);
}
}
}
else
{
MessageBox.Show("No other running applications found.");
}
}
protected override void WndProc(ref Message message)
{
//filter the RF_TESTMESSAGE
if (message.Msg == WM_CUSTOM_MESSAGE)
{
int numberReceived = (int)message.LParam;
string str=string.Empty;
//Do ur job with this integer
switch (numberReceived)
{
case 101: str = "start";
break;
case 102: str = "stop";
break;
case 103: str = "error";
break;
}
this.listBox1.Items.Add(str + "Received message RF_TESTMESSAGE");
}
else
{
base.WndProc(ref message);
}
////filter the RF_TESTMESSAGE
//if (message.Msg == RF_TESTMESSAGE)
//{
// //display that we recieved the message, of course we could do
// //something else more important here.
// this.listBox1.Items.Add("Received message RF_TESTMESSAGE");
//}
//be sure to pass along all messages to the base also
//base.WndProc(ref message);
}