Erlang: Using 32 bit NIFs under a 64 bit VM - erlang

Is there a way to use a 32bit NIF from a 64 bit Erlang (under Windows)?
Seems impossible, but maybe there is a way to achieve this?

My only suggestion (too silly) - you can write 32-bit out-of-proc port driver as wrapper of your NIF and run it in separate process. Of course, erlang node in this case should interact not with NIF but with external port program. But you can consider this as joke ;-)

Related

NIF to wrap my multi-threaded C++ code

I have a C++ code that implement a special protocol over the serial port. The code is multi-threaded and internally polls the serial port and do its own cyclic processing. I would like to call this driver from erlang and also receive events from this driver. My concern is that this C++ code is multi-threaded and also statefull meaning that when I call a certain function on the driver, it caches things internally which will be used/required on the subsequent calls of the driver. My questions are
1.Does NIF run in the same os process as the rest of my erlang proceses or NIF is launched in a separate os process?
2.Does it make sense to warp this multi-threaded stateful C++ code with NIF?
4.If NIF is not the right approach, what is the better way for me to make Elrang talk back and forth with this C++ code. I also prefer my C++ code to be inside the same OS process as the rest of my Erlang processes and as it looks like linked-in drivers are an option but not sure if the multi-threaded nature of my C++ code will be ok to that model. Plus I hear they can mess up elrang scheduler?
Unlike ports, NIFs are run within Erlang VM process, similar to drivers. Because of that, any NIF crashes will bring VM down as well. And, answering in advance, to your last question, NIFs, like drivers, may block your scheduler.
That depends on the functionality you are implementing by this C++ code. Due to the answer 1), you probably want to avoid concurrency in the C++ part, since it's a potential source of errors. It's not always possible, of course. But if you are implementing, say, some workers pool, go ahead and implement 1-threaded code, spawning it as many times as you need.
Drivers can be multi-threaded too, with same potential problems and quite similar performance (well, still slightly faster than NIFs). If you are not completely sure about your C++ code stability, use it as an Erlang port.
Speaking of the difference between NIFs and drivers, the former is synchronous natively, and the latter can be asynchronous (which can be really a huge advantage if you don't want to receive any answers for most of the commands). Drivers are easier to mess up and harder to implement (but once you grasp the main patterns and problems, they seem okay, actually).
Here's a good start for drivers:
http://www.erlang.org/doc/apps/erts/driver.html
And something similar (behold the difference in complexity) for NIFs:
http://www.erlang.org/doc/tutorial/nif.html

How can I call a 32-bit DLL from 64-bit code?

I have some 32-bit DLLs that don't have matched 64-bit DLLs. How can I invoke these DLLs from a 64-bit application written in Delphi XE2?
No, you cannot directly do this. A 64 bit process can only execute 64 bit code, and a 32 bit process can only execute 32 bit code.
The trick is to use multiple processes.... (Note this can be done for non visual code, and even for GUI elements, though there can be some small but problematic behaviors for visual elements.)
The most common solution is to wrap the 32 bit dll in an out of process COM server, which you can call across the 64/32 bit barrier. (This goes both ways, you can create a 64 bit out of process COM server and call it from a 32 bit application also.)
Yes, there are other ways to conceive of this, but the most common is to use COM:
Create a new 32 bit out of process COM server that hosts your 32 bit
DLL and exposes the needed functionality from the 32 bit dll.
Call this COM server from your 64 bit code
I should add that it is also possible to create the new 32 bit COM server as an in-process COM server, and then configure COM+ to run it. COM+ will run it out of process, and magically run your 32 bit in process COM server out of process, where you can call it from 32 and 64 bit code transparently, as if it was in process. (Note, if the COM server is a GUI control, going out of process may or may not work. The team I work with has done it successfully, but there are complexities -- some of which cannot be surmounted -- related to hooking parent windows and controls that cannot be done across the process boundary.)
You can use the same exact technique used to call 64 bit dlls from 32 bit code.
See http://cc.embarcadero.com/Item/27667
"Just" make the contrary: run a background 32 bit process, the communicate from your 64 bit process with it using a memory mapped buffer.
But this is definitively not an easy task. You'll have to rewrite some asm code. I wrote some article about how it works.
The out-of-process COM option is perhaps the easiest to implement. Or use a more simple IPC - like WM_COPYDATA message or any other mean. But you'll definitively need another 32 bit process to link to the 32 bit libraries.
I had the same issue some time back and found this link:32-bit DLLs in 64-bit environment
The 32-bit DLL was written in Delphi, ages ago, and we now had a need to call it from a 64-bit platform- but we don't have a 64-bit Delphi.
I've made it work- though it seems a bit of a kludge, it was better than getting the DLL rewritten in 64-bit (we'd have had to purchase a 64-bit version of Delphi, or start from scratch in something else).
NB while this needs some hacking, no programming is required- it uses components that came with Windows. Works in (at least) Windows 7, Windows 2008.

Writing data to I/O address

i have a device (cash drawer) and i would like to directly communicate with the device. I know that its on address f1. Also openbit is 01.
As i've understood so far, i'd need to send 1 to memory address f1 and the cash drawer should open. Though using asm, i get access violation. Then again i've read that windows does not let you communicate directly to device i/o addresses (need to use win). What would be the correct way to send the data to that address.
Note that i cannot use drivers, because i can't communicate with the driver inside my application.
Op. system is win7.
Thanks in advance!
There was a library called inpout32.dll that allowed direct port access you can find it here
http://logix4u.net/Inpout32.dll_Discussion/write_DELPHI_for_inpout32.dll.html
But i don't know if supports windows 7.
In addition to the excellent suggestions above, check out this delphi code for writing and reading I/O. We have used the GWIOPM to do what you are asking, but note that it will be ok for 32-bit versions of Windows up to W7 etc (as is the case for most 'free' drivers). For 64-bit Windows you need a signed kernel driver. For this there are few things available at the moment. We had to write our own.
Why can't you communicate with the driver from your application? It's the best way for ring 3 application to talk with hardware in a safe manner.
However, if you really insist using drivers, you can try going to ring 0 and do direct access. It's much harder than in previous Windows versions (XP and before) but it's possible. I haven't done it myself since I don't have Windows 7, but you can try asking in asm programming forum anywhere.

Running the erlang vm inside a process

It's possible to run the erlang VM inside a process?
I'm asking this because I'm trying to use some code using the erl_nif, witch is very cool indeed, but I have to send information back to the process that could possibily spawn the VM. The only approach I've thinked is to create some IPC communication, like pipes or reading from COUT, but this imposes the need of some protocol, and would be cool if I could call what I need directly from the function response.
Even don't mention that Erlang VM manage OS threads and has event loop, how do you want it will be stable and predictable when running inside an unpredictable OS process? No, you can't run Erlang VM inside an OS process.
Think about Erlang VM as about operating system:
Write all your code in Erlang;
Use NIFs/Port drivers only if you really need more speed. But be aware - you're in "kernel mode" now!
Use Ports/Erl_interface/C Nodes if you have many code written in some other language;

When I make a C plugin for erlang will it take full advantage of the spawning system? Does it block?

eg I have a program that eats a lot of CPU. I make a C plugin that can interact with erlang. I spawn 16 threads with SMP +16. Will it give me a similar performance compared to something like pthreads on a multicore? The threads do not need to communicate with each other.
"C plugin" is not clearly defined in the erlang context.
Either you are writing a port which basically forks a system process.
Or you are writing a linked in driver which runs in the same context as the Erlang vm.
In both cases you can take advantage of multicore cpu's. The first case just relies on the OS to place the OS processes on different CPU's (which any decent SMP OS should be capable of).
In the second case I'm not so sure but I would expect the drivers to run on different CPU cores also. Unless you have a strong cause for using linked drivers and you know exactly what you are doing I recommend against them for complexity and stability reasons. If a port crashes Erlang is notified and can restart it or take other precautions. If a driver crashes the whole Erlang vm is taken down hard.
The main question is what part of the problem you want to solve in Erlang, if you use erlang only to start your "plugins" this can be much easier be solved just starting processes from the shell, since your "threads" don't need to communicate, why not pass the parameters on the commandline and fork working processes from a shell script?

Resources