The Window-Procedure in the Win32 API must be static \ global function since it cannot take a class-object (the this) parameter. One can of-course use workarounds like a hWnd->object dictionary and such.
I wonder if D has a way to elegantly solve it, like create a tiny member function copy for each object (to call the object's real handler) or anonymous function that I can assign to WNDCLASS.lpfnWndProc (I know there are anonymous functions, but I cannot use the extern(Windows) property on them) ?
Can I do something like this :
class Window {
extern (Windows)
LRESULT delegate (HWND hWnd, UINT msg, WPARAM w, LPARAM l) MyWinProcDelegate;
this() {
MyWinProcDelegate = &Events;
}
extern (Windows)
LRESULT Events (HWND hWnd, UINT msg, WPARAM w, LPARAM l) {
MessageBoxA(null , "Success!!!" , null ,0);
return DefWindowProcA(hWnd, message, wParam, lParam);
}
}
(Omitting the registration\creation\msg-loop...)
The Events() doesn't seem to fire... am I missing something ?
Here I made this for you (based on BCS' answer):
version (Windows)
{
import std.c.windows.windows;
void makeExecutable(ubyte[] code)
{
DWORD old;
VirtualProtect(code.ptr, code.length, PAGE_EXECUTE_READWRITE, &old);
}
}
else
version (linux)
{
import core.sys.posix.sys.mman;
import core.sys.posix.unistd;
static if (!is(typeof(&mprotect)))
extern(C) int mprotect(void*, size_t, int);
void makeExecutable(ubyte[] code)
{
auto pageSize = sysconf(_SC_PAGE_SIZE);
auto address = ((cast(size_t)code.ptr) & ~(pageSize-1));
int pageCount =
(address/pageSize == (address+code.length)/pageSize) ? 1 : 2;
mprotect(cast(void*)address, pageSize * pageCount,
PROT_READ | PROT_WRITE | PROT_EXEC);
}
}
else
static assert(0, "TODO");
R function(A) delegate2function(R, A...)(R delegate(A) d)
{
enum size_t TEMPLATE1 = cast(size_t)0x01234567_01234567;
enum size_t TEMPLATE2 = cast(size_t)0x89ABCDEF_89ABCDEF;
static R functionTemplate(A args)
{
R delegate(A) d;
d.ptr = cast(typeof(d.ptr ))TEMPLATE1;
d.funcptr = cast(typeof(d.funcptr))TEMPLATE2;
return d(args);
}
static void functionTemplateEnd() {}
static void replaceWord(ubyte[] a, size_t from, size_t to)
{
foreach (i; 0..a.length - size_t.sizeof + 1)
{
auto p = cast(size_t*)(a.ptr + i);
if (*p == from)
{
*p = to;
return;
}
}
assert(0);
}
auto templateStart = cast(ubyte*)&functionTemplate;
auto templateEnd = cast(ubyte*)&functionTemplateEnd;
auto templateBytes = templateStart[0 .. templateEnd - templateStart];
// must allocate type with pointers, otherwise GC won't scan it
auto functionWords = new void*[(templateBytes.length / (void*).sizeof) + 3];
// store context in word-aligned boundary, so the GC can find it
functionWords[0] = d.ptr;
functionWords[1] = d.funcptr;
functionWords = functionWords[2..$];
auto functionBytes = (cast(ubyte[])functionWords)[0..templateBytes.length];
functionBytes[] = templateBytes[];
replaceWord(functionBytes, TEMPLATE1, cast(size_t)d.ptr );
replaceWord(functionBytes, TEMPLATE2, cast(size_t)d.funcptr);
makeExecutable(functionBytes);
return cast(typeof(return)) functionBytes.ptr;
}
void main()
{
import std.stdio;
auto context = 42;
void del(string s)
{
writeln(s);
writeln(context);
}
auto f = delegate2function(&del);
f("I am a pretty function");
}
Tested on Windows 32-bit and Linux 64-bit.
How about storing this in the window itself, with SetWindowLong?
One very un-portable solution would be to dynamically create a function that wraps the call. I would do this by writing a function that looks like this:
extern(C) RetType TestFn(Arg arg /* and any others */) {
Class c = cast(Class)(0xDEAD_BEEF);
return c.Method(arg);
}
You can then compile this function as un-optimized PIC, de-compile it, and find a byte sequence that can be mashed into what you need. The end result would be a type (likely a struct) that has a methoud returning a function pointer and that, when constructed, populates an internal void array with the bytes you found from the above step and pokes the object in question into the appropriate places.
A slightly more advanced solution would populate a delegate with both the object and the method pointer so both can be provided to the constructor. An even more advanced solution would template the type and take advantage of knowledge of the C and D calling conventions to dynamically generate the argument forwarding code.
Related
I have this code in 64bit dll on Windows
#define TEMPLATENEST_API __declspec(dllexport)
extern "C" TEMPLATENEST_API void templatenest_init(void** object);
void templatenest_init(void** object)
{
//TemmplNest
*object =(void*) new TemplateNestClass();
}
In raku,
sub templatenest_init(Pointer is rw) is native(dl) { * }
my Pointer $class_pointer;
templatenest_init($class_pointer);
templatenest_init($class_pointer)
However, after this line, $class_pointer was 0.
Somehow the value of a the class pointer does not arrive in Raku.
I checked in a Debugger that *object was set to non zero value.
Signature of the exported function
2 1 00025621 templatenest_init = #ILT+5660(templatenest_init)
Minimal example:
Use Microsoft VIsual studio 2019 compile as dll library 64 bit
raku:
use v6;
use Data::Dump;
use NativeCall;
#constant dl = 'D:\m\cpp\TemplateNest\template-nest-rakudl\TemplateNestDll.dll';
constant dl = 'D:\m\cpp\TemplateNest\x64\Debug\DllMinitest.dll';
sub get_dll_name()
{
if $*VM.osname eq 'linux' {
return 'templatenest';
}
else
{
return dl;
}
}
sub templatenest_init(Pointer is rw) is native(get_dll_name) { * }
my Pointer $class_pointer;
templatenest_init($class_pointer);
say "{$class_pointer.Int}";
# it prints 0.
export.cpp:
#define TEMPLATENEST_API __declspec(dllexport)
class TemplateNestClass {
};
extern "C" TEMPLATENEST_API void templatenest_init(void** object);
void templatenest_init(void** object)
{
//TemmplNest
*object = (void*) new TemplateNestClass();
}
dllmain:
// dllmain.cpp : Defines the entry point for the DLL application.
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
A work around seems to work.
extern "C" TEMPLATENEST_API void templatenest_init(__int64 * object);
sub templatenest_init(int64 is rw ) is native(get_dll_name) { * }
my int64 $class_pointer;
templatenest_init($class_pointer);
Actual answer:
The pointer needs to be initialised like this:
my Pointer $class_pointer = Pointer.new();
All Pointer stuff needs to be new-ed.
Another example:
my Pointer[Str] $html = Pointer[Str].new();
I have implemented a custom storage interface in libtorrent as described in the help section here.
The storage_interface is working fine, although I can't figure out why readv is only called randomly while downloading a torrent. From my view the overriden virtual function readv should get called each time I call handle->read_piece in piece_finished_alert. It should read the piece for read_piece_alert?
The buffer is provided in read_piece_alert without getting notified in readv.
So the question is why it is called only randomly and why it's not called on a read_piece() call? Is my storage_interface maybe wrong?
The code looks like this:
struct temp_storage : storage_interface
{
virtual int readv(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
// Only called on random pieces while downloading a larger torrent
std::map<int, std::vector<char> >::const_iterator i = m_file_data.find(piece);
if (i == m_file_data.end()) return 0;
int available = i->second.size() - offset;
if (available <= 0) return 0;
if (available > num_bufs) available = num_bufs;
memcpy(&bufs, &i->second[offset], available);
return available;
}
virtual int writev(file::iovec_t const* bufs, int num_bufs
, int piece, int offset, int flags, storage_error& ec)
{
std::vector<char>& data = m_file_data[piece];
if (data.size() < offset + num_bufs) data.resize(offset + num_bufs);
std::memcpy(&data[offset], bufs, num_bufs);
return num_bufs;
}
virtual bool has_any_file(storage_error& ec) { return false; }
virtual ...
virtual ...
}
Intialized with
storage_interface* temp_storage_constructor(storage_params const& params)
{
printf("NEW INTERFACE\n");
return new temp_storage(*params.files);
}
p.storage = &temp_storage_constructor;
The function below sets up alerts and invokes read_piece on each completed piece.
while(true) {
std::vector<alert*> alerts;
s.pop_alerts(&alerts);
for (alert* i : alerts)
{
switch (i->type()) {
case read_piece_alert::alert_type:
{
read_piece_alert* p = (read_piece_alert*)i;
if (p->ec) {
// read_piece failed
break;
}
// piece buffer, size is provided without readv
// notification after invoking read_piece in piece_finished_alert
break;
}
case piece_finished_alert::alert_type: {
piece_finished_alert* p = (piece_finished_alert*)i;
p->handle.read_piece(p->piece_index);
// Once the piece is finished, we read it to obtain the buffer in read_piece_alert.
break;
}
default:
break;
}
}
Sleep(100);
}
I will answer my own question. As Arvid said in the comments: readv was not invoked because of caching. Setting settings_pack::use_read_cache to false will invoke readv always.
I have been trying various code snippets here and there, but still not successful.I am simply trying to find one of the open windows (it is the Browser window) using FindWindow(NULL,WINDOWTITLE), with a specific Title string. Once I get the handle of the window, I need the coordinates using GetWindowRect.
This code gets me the coordinates, but seems like it's in an infinite loop, there are about a 100 lines of output with the coordindates, should be just 1. I don't see any while construct (originally a Java programmer)... wonder why it's repeating...
struct WindowInfo
{
HWND m_hWnd;
string m_title;
WindowInfo(HWND hwnd, string title) : m_hWnd(hwnd), m_title(title) {}
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
vector<WindowInfo*> & windows = *(vector<WindowInfo*>*)lParam;
char title[256];
HANDLE wndHandle;
LPCWSTR WINDOWTITLE = L"eBargain 2 Share - Windpos Internet Explorer";
RECT rRect;
LPRECT lpRect;
RECT rc;
hwnd = FindWindow(NULL,WINDOWTITLE);
GetWindowRect(hwnd,&rc);
printf("Position: %d x %d\tSize: %d x %d\n",rc.left,rc.top,rc.right- rc.left,rc.bottom-rc.top);
/* Enumerating through all the windows tells me that I am on the right track... (Should I just try to find the TITLE STRING by comparing every title from the following enumeration ?
*/
GetWindowTextA(hwnd, title, 256);
windows.push_back(new WindowInfo(hwnd,title));
// printf("%s\n", title);
return TRUE;
}
int main()
{
vector<WindowInfo*> windows;
BOOL ret = EnumWindows(EnumWindowsProc, (LPARAM) &windows);
if ( ret )
{
//windows have windowinfo of all enumerated windows
}
}
Your EnumWindowsProc seems to be a bit confused - are you enumerating or using FindWindow?
If you enumerate, simply get the window title and compare to the string you search for:
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
char title[256];
if (GetWindowTextA(hwnd, title, 256)) {
if (strcmp(title, "eBargain 2 Share - Windpos Internet Explorer") == 0) {
/* GetWindowRect ... */
}
}
return TRUE;
}
Or, if you're using FindWindow, no need to enumerate:
int main() {
HWND hwnd = FindWindowA(0, "eBargain 2 Share - Windpos Internet Explorer");
if (hwnd) {
/* GetWindowRect ... */
}
}
I am using QGraphicsScene/QGraphicsView pair in my project
I have performance issue with this pair.
I added my custom graphics items to scene and displayed the contents with view. After that my custom graphics items paint method continuously called by scene(just like infinite loop). This makes %25 of CPU usage(approximately 400 items on scene). What may cause this behaviour?
Here is one my item implementation:
class LevelCrossingItem : public QGraphicsWidget
{
public:
LevelCrossingItem(QString _id,qreal _x,qreal _y);
~LevelCrossingItem();
QRectF boundingRect() const;
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = 0 */);
void readStateBits();
bool isClosed();
bool isGateArmBroken();
bool isOpenedDuringRouteTanzimCompleted();
bool hasDataConsistencyWarning();
int type() const {return Type;}
private slots:
void setVisible(bool);
private:
enum {Type = FIELDLEVELCROSSING};
QString m_id;
QString m_source;
short m_closedState;
short m_brokenGateArmState;
short m_openedDuringRouteTanzimCompletedState;
short m_dataConsistencyWarningState;
QBitArray stateBitArray;
qreal x,y;
QSvgRenderer *renderer;
};
#include "levelcrossing.h"
LevelCrossingItem::LevelCrossingItem(QString _id,qreal _x,qreal _y):m_id(_id),x(_x),y(_y),stateBitArray(4)
{
m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
renderer = new QSvgRenderer;
setStateArray(stateBitArray);
setZValue(-0.5);
}
LevelCrossingItem::~LevelCrossingItem()
{
delete renderer;
}
void LevelCrossingItem::setVisible(bool visible)
{
QGraphicsItem::setVisible(visible);
}
QRectF LevelCrossingItem::boundingRect() const
{
return QRectF(QPointF(x,y),sizeHint(Qt::PreferredSize));
}
QSizeF LevelCrossingItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
return QSizeF(50,270);
}
void LevelCrossingItem::readStateBits()
{
m_closedState = property("Closed").toInt();
m_brokenGateArmState = property("Broken").toInt();
m_openedDuringRouteTanzimCompletedState = property("OpenedOnRouteWarning").toInt();
m_dataConsistencyWarningState = property("DataConsistencyWarning").toInt();
stateBitArray.setBit(0,qvariant_cast<bool>(m_closedState));
stateBitArray.setBit(1,qvariant_cast<bool>(m_brokenGateArmState));
stateBitArray.setBit(2,qvariant_cast<bool>(m_openedDuringRouteTanzimCompletedState));
stateBitArray.setBit(3,qvariant_cast<bool>(m_dataConsistencyWarningState));
setStateArray(stateBitArray);
}
void LevelCrossingItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
Q_UNUSED(option);
Q_UNUSED(widget);
readStateBits();
m_closedState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("closed")
: m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
m_brokenGateArmState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("broken")
: m_source = m_source;
if(m_openedDuringRouteTanzimCompletedState == Positive)
{
setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),true);
if(stateChanged())
emit itemAlarmOccured(m_id,LevelCrossingIsOpenDuringTanzimCompleted);
}
else
setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),false);
if(m_dataConsistencyWarningState == Positive)
{
setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),true);
if(stateChanged())
emit itemAlarmOccured(m_id,LevelCrossingDataConsistency);
}
else
setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),false);
renderer->load(m_source);
renderer->render(painter,boundingRect());
}
bool LevelCrossingItem::isClosed()
{
return m_closedState == Positive;
}
bool LevelCrossingItem::isGateArmBroken()
{
return m_brokenGateArmState == Positive;
}
bool LevelCrossingItem::isOpenedDuringRouteTanzimCompleted()
{
return m_openedDuringRouteTanzimCompletedState == Positive;
}
bool LevelCrossingItem::hasDataConsistencyWarning()
{
return m_dataConsistencyWarningState == Positive;
}
I read x and y coordinates from xml file. For this item x and y coordinates are 239,344 respectively
Most likely your graphics item has mistakes in the implementation. I had similar behavior, but I was unable to figure out what exactly causes it. I suspect that this happens when you draw outside of the bounding rect. This triggers some clean up routine, which in turn causes redraw of the item, and here goes the loop. Eventually I resolved the issue by carefully inspecting the implementation of my custom graphics item and making sure that:
These is no painting outside of the MyGraphicsItem::boundingRect. Use painter->setClipRect(boundingRect())
MyGraphicsItem::shape does not cross with the MyGraphicsItem::boundingRect.
If you override any other QGraphicsItem functions, make sure that your implementation is correct.
Hope this helps. Feel free to post the source code of your graphics item, it will be easier to find the problem.
How would you set the object data that is shared between threads and needs to be updated once after the complete cycle of (say) two threads in busy loop?
CRITICAL_SECTION critical_section_;
int value; //needs to be updated once after the cycle of any number of threads running in busy loop
void ThreadsFunction(int i)
{
while (true)
{
EnterCriticalSection(&critical_section_);
/* Lines of Code */
LeaveCriticalSection(&critical_section_);
}
}
Edit: The value can be an object of any class.
Two suggestions:
Make the object itself thread safe.
Pass the object into the thread as instance data
I'll use C++ as a reference in my example. You can easily transpose this to pure C if you want.
// MyObject is the core data you want to share between threads
struct MyObject
{
int value;
int othervalue;
// all all the other members you want here
};
class MyThreadSafeObject
{
private:
CRITICAL_SECTION _cs;
MyObject _myojbect;
bool _fLocked;
public:
MyThreadSafeObject()
{
_fLocked = false
InitializeCriticalSection();
}
~MYThreadSafeObject()
{
DeleteCriticalSection();
}
// add "getter and setter" methods for each member in MyObject
int SetValue(int x)
{
EnterCriticalSection(&_cs);
_myobject.value = x;
LeaveCriticalSection(&_cs);
}
int GetValue()
{
int x;
EnterCriticalSection(&_cs);
x = _myobject.value;
LeaveCriticalSection(&_cs);
return x;
}
// add "getter and setter" methods for each member in MyObject
int SetOtherValue(int x)
{
EnterCriticalSection(&_cs);
_myobject.othervalue = x;
LeaveCriticalSection(&_cs);
}
int GetOtherValue()
{
int x;
EnterCriticalSection(&_cs);
x = _myobject.othervalue;
LeaveCriticalSection(&_cs);
return x;
}
// and if you need to access the whole object directly without using a critsec lock on each variable access, add lock/unlock methods
bool Lock(MyObject** ppObject)
{
EnterCriticalSection(&_cs);
*ppObject = &_myobject;
_fLocked = true;
return true;
}
bool UnLock()
{
if (_fLocked == false)
return false;
_fLocked = false;
LeaveCriticalSection();
return true;
}
};
Then, create your object and thread as follows:
MyThreadSafeObject* pObjectThreadSafe;
MyObject* pObject = NULL;
// now initilaize your object
pObjectThreadSafe->Lock(&pObject);
pObject->value = 0; // initailze value and all the other members of pObject to what you want them to be.
pObject->othervalue = 0;
pObjectThreadSafe->Unlock();
pObject = NULL;
// Create your threads, passing the pointer to MyThreadSafeObject as your instance data
DWORD dwThreadID = 0;
HANDLE hThread = CreateThread(NULL, NULL, ThreadRoutine, pObjectThreadSafe, 0, &dwThreadID);
And your thread will operate as follows
DWORD __stdcall ThreadFunction(void* pData)
{
MyThreadSafeObject* pObjectThreadSafe = (MyThreadSafeObject*)pData;
MyObject* pObject = NULL;
while (true)
{
/* lines of code */
pObjectThreadSafe->SetValue(x);
/* lines of code */
}
}
If you want implement thread safe update of an integer you should better use InterlockedIncrement and InterlockedDecrement or InterlockedExchangeAdd functions. See http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx.
If you do need use EnterCriticalSection and LeaveCriticalSection you will find an example in http://msdn.microsoft.com/en-us/library/ms686908(v=VS.85).aspx, but I recommend you to use EnterCriticalSection inside of __try block and LeaveCriticalSection inside of the __finally part of this blocks.