Jump to content

Anders Melander

Members
  • Content Count

    2312
  • Joined

  • Last visited

  • Days Won

    119

Everything posted by Anders Melander

  1. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Make that: In that case your method can be declared "safecall".
  2. Anders Melander

    do any git tools work like this?

    Once again: As far as I can tell there's nothing special in the work flow your describe. It's perfectly normal to have a branch per ticket, to change branch several times a day, to get interrupted while you're working on something that hasn't yet been committed, etc. The problems with Git you describe (changes disappearing, etc) are not problems with Git but with the way you use it; It will not overwrite your uncommitted changes unless you force it to. It is unclear to me what benefits your tool provides. It sounds like the problems it solves are already handled by the existing GUI Git clients.
  3. Anders Melander

    Compare byte array to ansichar

    As I wrote you cannot compare a byte (ansichar) to 13 bytes (byte array) for equality. Since the size is different they will always be different, so what you're asking isn't making sense. Are you trying to determine if the byte array contains the ansichar? function Contains(const Bytes: TByteArray; c: AnsiChar): boolean; begin for var b in Bytes do if (b = Ord(c)) then Exit(True); Result := False; end;
  4. Anders Melander

    Compare byte array to ansichar

    Assuming you meant AnsiString and not AnsiChar (it doesn't make sense to compare 13 bytes to 1 ansichar): function Compare(const Bytes: TByteArray; const Str: AnsiString): boolean; begin Result := (Length(Str) = SizeOf(Bytes)) and (CompareMem(@Str[1], @Bytes[0], SizeOf(Bytes)); end;
  5. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    I think you must have a bug somewhere else that is causing this. I can't spot a problem in the code you've posted. The following works for me with D10.3.1: function Test1: OleVariant; begin Result := VarArrayCreate([0, 1], varOleStr); Result[0] := 'Hello'; Result[1] := 'World'; end; function Test2: OleVariant; var V: OleVariant; begin V := VarArrayCreate([0, 1], varOleStr); V[0] := 'A kitten dies...'; V[1] := '...every time you use variant arrays'; Result := V; end; procedure DoTest; var V: OleVariant; begin V := Test1; V := Test2; end; Try reproducing the problem in a new empty application.
  6. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Have you tried VarArrayCreate(..., varOleStr)? I can't see why you would get an error assigning one OleVariant to another but it would help if you specified what error you're getting.
  7. Anders Melander

    TFDMemTable in use by different threads

    Yes. Moving the cursor in a clone does not affect the other clones. As I read that post read access to a cloned dataset is thread safe.
  8. Anders Melander

    remove part of string and compare

    Yes, it was poorly expressed on my part. If they went through the message queue then the application wouldn't appear hung.
  9. Anders Melander

    remove part of string and compare

    Generally speaking, the API of most Windows common controls goes through the windows message queue. So my guess is that for each item in the listbox there's a lot of messages going back and forth while the listbox is populated and that's an enormous overhead. If you break the application in the debugger while the list is loading you can see what it's doing.
  10. Anders Melander

    Compile code on the fly...?

    Okay. I'll try with a simpler example (apologies to @Kas Ob. if he/she/they already covered it, but it's friday and TLDR). Byte code is just the instruction set for a specialized virtual CPU so in this case it's a virtual CPU that only knows how to search stuff. A byte code compiler is a compiler that transforms "something" (in this case search parameters) into the virtual CPU assembler. The implementation of the virtual CPU is called an interpreter if it executes the byte code instruction from scratch each time you execute the "byte code program". If it instead compiles the byte code into actual processor opcodes the first time and then execute those the first and subsequent times, then it's called just-in-time compiler. One of the first pascal implementation was UCSD Pascal which ran on the UCSD p-System - a byte code virtual machine. P.S. You really should try to read about and understand these old concepts. While they might not seem relevant to you now, understanding and knowing about them can only improve your skills.
  11. Anders Melander

    Compile code on the fly...?

    https://en.wikipedia.org/wiki/Interpreter_(computing)#Bytecode_interpreters
  12. Anders Melander

    Batch Reading Emails from Windows Explorer

    So you are doing it with Outlook which again prompts me to ask why you're not also handling the eml files the same way (after importing them into Outlook) instead of handling them in two different ways? Personally I would probably: Load the msg file into an IStorage with StgOpenStorage Get an IMessage from the IStorage with OpenIMsgOnIStg Extract the IMessage properties with HrGetOneProp or IMessage.OpenProperty
  13. Anders Melander

    Batch Reading Emails from Windows Explorer

    Yes I understood that. I was talking about your statement : "drop the msg files into Outlook and handle them there somehow".
  14. Anders Melander

    Batch Reading Emails from Windows Explorer

    If I'm understanding what you're saying you are going drop the msg files into Outlook and handle them there somehow. If that's an option then why not also handle the eml files this way?
  15. Anders Melander

    Batch Reading Emails from Windows Explorer

    I would guess that no other types use it. It's not a very friendly format. I can't speak authoritatively on the subject but if IMessage is a MAPI interface then in theory it should work with all MAPI providers. Unfortunately I don't think there's many applications left that support MAPI. I doubt it but it should be easy to determine since you have the source...
  16. Anders Melander

    Batch Reading Emails from Windows Explorer

    Outlook msg files are COM Structured Storage files in the CFB3 (Compound File Binary) format. Here's file file format specification: http://msdn.microsoft.com/en-us/library/cc463912.aspx You can use the IStorage interface to load the file (via IStream) but you will need to locate and extract the desired properties manually. You can find tons of code on the net that shows how to do that and I think the above specs contains the names of the properties. I also think the last version of the Drag and Drop Component Suite I released even contained some code that did it. AFAIR there's also an OpenIMsgOnIStg API function that can do some of the work for you but I think it might require that Outlook is installed.
  17. Anders Melander

    Interlocked API and memory-mapped files

    Okay, here you go. Source and simple demo attached. Usage: Producer var FRingBuffer := TSharedMemoryRingBuffer.Create('FooBar', 1024*1024); // 1Mb ... // String FRingBuffer.Enqueue('Hello world'); // Raw bytes var Buffer: TBytes; ... FRingBuffer.Enqueue(Buffer); Consumer var FRingBuffer := TSharedMemoryRingBuffer.Create('FooBar', 1024*1024); // 1Mb ... // Strings while (True) do begin // Just remove the WaitFor to use polling instead if (FRingBuffer.WaitFor(100) = wrSignaled) then begin var s. string; if (FRingBuffer.Dequeue(s)) then ...do something with string... end; ... end; // Raw bytes while (True) do begin // Just remove the WaitFor to use polling instead if (FRingBuffer.WaitFor(100) = wrSignaled) then begin var Buffer: TBytes; if (FRingBuffer.Dequeue(Buffer)) then ...do something with buffer... end; ... end; amSharedMemory.pas SharedMemory.zip
  18. Anders Melander

    Interlocked API and memory-mapped files

    @A.M. Hoornweg Thanks for the detailed explanation. I understand your challenge much better now. I think it's essential that you realize that the overhead of the lock itself is not going to be a factor at all and instead focus on minimizing the time the lock is held - i.e. the time to transfer data to and from the shared memory buffer. My recommendation would be to start with a simple solution and if that turns out not to be fast enough then you can try to come up with something better. I don't know anything about the actual amount of data you're processing but I think I would strive to process it in many small chunks instead of few large chunks. On the producer side I would write data packets to a (fast) lock free queue and have a separate thread read from that queue and write them to the (slower) shared memory queue. If it's essential that the producer isn't blocked then you will have to accept that data can be dropped if the consumer isn't able to keep up, but I guess you already know that. Again, if you want it I have a ready to use implementation of a shared memory circular buffer that has been used in production for many, many years.
  19. Anders Melander

    Interlocked API and memory-mapped files

    Are you kidding me? What you are asking for is apparently a wheelbarrow while the rest of us are suggesting different ways to build a drag racer I don't get why you don't just use a TMutex to protect the ring buffer structure and a TSemaphore to signal availability. I mean it's like around 10 lines of extra code compared to the 2-300 lines of code you will need to implement the ring buffer in shared memory. You're aware that you can't store pointers in shared memory, right?
  20. Anders Melander

    Interlocked API and memory-mapped files

    So how will you use a spinlock to signal the consumer thread that data is available without doing busy wait?
  21. Anders Melander

    Interlocked API and memory-mapped files

    And it's extremely subject to race conditions. https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185
  22. Anders Melander

    Interlocked API and memory-mapped files

    Why not just use the traditional synchronizations mechanism provided by the OS and keep things simple? It seems pointless focusing on micro optimizing the concurrency control of a buffer backed by virtual memory and accessed synchronously. The sync mechanism is not going to be the bottleneck. I have the code for a shared memory ring buffer somewhere if the OP is interested. I used it a few decades ago to pipe CodeSite log messages between a producer and a consumer service. The consumer wrote the log to disk.
  23. Call me old fashioned but the way you've formatted your code makes it close to unreadable to me.
  24. Anders Melander

    How do I enumerate all properties of a Variant?

    Instead of waiting on the back and forth I'll assume that what we have here is a classic case of the XY problem. To determine what properties a WMI object exposes you can use a tool like WMI Explorer (there are many other tools like that, this is just the first one I found).
×