感谢您花费大量时间尝试回答这个问题。
我正在尝试创建一个从 DLL 中打开一个窗口的 DLL。我正在使用 C# 运行创建的 DLL。DLL 在 VSC 中创建,C# 代码使用 VSC# 编译。
该窗口通过调用Initalize(const char* title)
或Initalize(string title)
在 C# 中进行集成。无论我如何尝试,创建的窗口都会被创建、运行,但它的标题不是传递的字符串。我试过用const wchar_t*
, LPCSTR
, LPCWSTR
, System.String
, [MarshalAs(UnmanagedType.LPStr)]
, [MarshalAs(UnmanagedType.LPWStr)]
. 我尝试将传递的字符串复制到一个动态分配的数组中,该数组使用 new/delete 和 malloc/free 进行分配。
我认为这是一个指针错误,但最让我感动的是,printf("passed string: %s", title)
在我的 C++ 代码中,在控制台中打印了正确的标题,但我的窗口看起来像:
我的 C++ 代码是:
// GameInterface.cpp : Defines the exported functions for the DLL application.
//
#include "GameInterface.h"
#include <Windows.h>
// OpenGL was origionally implimented into here, and removed to be asked on StackOverflow.
LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hInstance = NULL;
ATOM wclAtom = NULL;
HWND hWnd = NULL;
HDC hDC = NULL;
HGLRC hRC = NULL;
bool running = false;
#if _DEBUG
#include <stdio.h>
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
#if _DEBUG
printf("GameInterface.dll::DllMain()\n");
#endif
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
hInstance = hModule;
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
Shutdown();
break;
}
return TRUE;
}
GAMEINTERFACE_API int Initalize(const char* title)
{
if (hWnd != NULL)
return 0;
#if _DEBUG
printf("GameInterface.dll::Initalize(\"%s\")\n", title);
#endif
int length = strlen(title);
char* name = new char[length+1];
strcpy(name, title);
WNDCLASSEXA wcl;
wcl.cbSize = sizeof(WNDCLASSEXA);
wcl.style = CS_OWNDC;
wcl.lpfnWndProc = DLLWindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = hInstance;
wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
wcl.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
wcl.lpszMenuName = NULL;
wcl.lpszClassName = name;
wcl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wclAtom = RegisterClassExA(&wcl);
#if _DEBUG
printf(" Registering Class\n");
#endif
if (!wclAtom)
{
#if _DEBUG
printf(" Error: Could not Register Class.\nExiting with error: %i\n", GetLastError() );
#endif
return 1;
}
#if _DEBUG
printf(" Creating Window\n");
#endif
hWnd = CreateWindowExA(0,
(LPCSTR)wclAtom,
(LPCSTR)name,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
512, 512,
NULL, NULL,
hInstance, NULL);
if (hWnd == NULL)
{
#if _DEBUG
printf(" Error: Window could not be created.\nExiting with error: %i\n", GetLastError() );
#endif
return 2;
}
#if _DEBUG
printf(" Displaying Window\n");
#endif
// to reduce size removed the code to initalize an OpenGL 3.1 context
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
running = true;
delete [] name;
#if _DEBUG
printf("Returning from GameInterface.dll::Initalize(const char*) with errors: %i\n", GetLastError() );
#endif
return 0;
}
GAMEINTERFACE_API void Shutdown()
{
if (running = false)
return;
#if _DEBUG
printf("GameInterface.dll::Shutdown()\n");
#endif
running = false;
wglMakeCurrent(NULL, NULL);
if (hRC != NULL) wglDeleteContext(hRC);
if (hDC != NULL) ReleaseDC(hWnd, hDC);
hRC = NULL;
hDC = NULL;
DestroyWindow(hWnd);
UnregisterClassA( (LPCSTR)wclAtom, hInstance);
wclAtom = NULL;
hWnd = NULL;
running = false;
}
GAMEINTERFACE_API int Update()
{
if ( (running == false) && (hWnd == NULL) )
return 1;
MSG msg;
if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (running == false)
return 1;
return 0;
}
GAMEINTERFACE_API void DrawFrame()
{
// Contained some OpenGL code that has now been removed.
}
LRESULT WINAPI DLLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
running = false;
break;
// handle other messages.
default: // anything we dont handle.
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0; // just in case
}
// GameInterface.h : Outlines the exported functions for the DLL application.
//
#pragma once
#ifdef GAMEINTERFACE_EXPORTS
#define GAMEINTERFACE_API __declspec(dllexport)
#else
#define GAMEINTERFACE_API __declspec(dllimport)
#endif
extern "C"
{
GAMEINTERFACE_API int Initalize(const char* title);
GAMEINTERFACE_API void Shutdown();
GAMEINTERFACE_API int Update();
GAMEINTERFACE_API void DrawFrame();
};
和 C# 代码:
// GameInterface.cs
//
using System;
using System.Runtime.InteropServices;
class GameInterface
{
const string GameInterfaceFile = "GameInterface_d.dll";
[DllImport(GameInterfaceFile)] public extern static int Initalize(string title);
[DllImport(GameInterfaceFile)] public extern static void Shutdown();
[DllImport(GameInterfaceFile)] public extern static int Update();
[DllImport(GameInterfaceFile)] public extern static void DrawFrame();
};
// Program.cs
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class Program
{
public static void Main()
{
string title = "OpenGL Window Title";
if (GameInterface.Initalize(title) != 0)
return;
while ( GameInterface.Update() == 0 )
{
// game logic.
GameInterface.DrawFrame();
}
GameInterface.Shutdown();
}
}
我被难住了,已经有一段时间了。