Light control & strobingTroubleshooting

Deploy a DLL to an embedded vision target and make it load

Why a DLL you deploy to an embedded vision target fails to load: architecture, dependencies and search paths, with a five-check test that isolates each layer.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does a DLL that transfers to the controller still fail to load?
  2. 02Is the FTP "I/O error" and the later "failed to load" one problem?
  3. 03Which build of the DLL matches my controller's processor and OS?
  4. 04How do I find every DLL my DLL depends on?
  5. 05Where do I put the DLL so the calling program actually finds it?
  6. 06What is the fastest way to prove the deployment before it reaches the line?
  7. 07When is the controller itself the reason it will not load?
  8. 08How do I keep the deployed DLL loading after a reboot or an update?
  9. 09Questions

A library that will not load on an embedded vision controller is a different kind of blocker: no lighting or lens change helps until the file runs. The symptoms look like two separate failures — a transfer that stops with an I/O error, and a copy that lands fine but still reports a load failure — yet both usually trace to the same three mismatches: processor architecture, missing dependencies and search paths. This guide is for engineers deploying their own libraries to vision controllers. You will place the file where the loader looks, ship what it imports, and run a five-check test that names the failing layer before the line sees the change.

Why does a DLL that transfers to the controller still fail to load?

Copying and loading are separate events: a completed transfer only places bytes in a folder, and the loader on the controller then refuses the file for its own reasons — an architecture or OS it cannot run, a dependent library the image lacks, or a path your call never searches.

The loader works in a fixed order. It reads the file header and checks the machine type against the calling process; a 32-bit process cannot load a 64-bit library, and the reverse, with no workaround. It then resolves every import by name, and the first missing name aborts the whole load. Only after both steps pass does your code run. That order explains the reports: a bitness mismatch, a missing dependency and a wrong path can all surface as the same generic failed-to-load message, so the message alone rarely names the layer. Work the three causes in order and the layer reveals itself.

Is the FTP "I/O error" and the later "failed to load" one problem?

No — they fail at different layers. An I/O error during transfer means the target refused the write: a path that does not exist, no write permission, a full disk or a locked destination. A load failure after a clean copy means the loader rejected the file.

Transfer-layer causes are short and checkable. Most FTP servers will not create directories, so create the destination folder yourself before the first send. Give the transfer account write rights to that folder. Check free space on the target. If the vision runtime holds the destination open — an earlier copy already loaded — stop the runtime, send, then restart. And set the client to binary mode before every send.

The load failure after a clean copy belongs to the loader, and the two connect through one quiet trap: the transfer lands in the FTP home directory while the call in your program points at the application folder. You fix the I/O error, the copy succeeds, the load still fails, and the fix looks useless. Reachability itself is a network topic — camera IP assignment failures after a network adapter change covers the addressing side.

Symptom Failing layer First test Fix
Transfer stops with an I/O error Target filesystem Write a small text file to the same folder Create the folder; use an account with write rights
Copy completes but the size differs Transfer mode Compare byte counts on both machines Resend in binary mode
Load fails right after a clean copy Loader Compare the build's machine type to the target Rebuild for the target's architecture and bitness
Load fails naming a missing file Dependency search List the imports; look for each on the controller Ship the missing files into the same folder
Loads in your session, not at boot Path resolution Print the resolved path at startup Use an absolute path beside the executable

Which build of the DLL matches my controller's processor and OS?

Match three things before you build: the processor family, the operating system and the calling process's bitness. A.dll only loads under a Windows-family loader, and a 32-bit process cannot load a 64-bit library — so on an x86 Intel controller with Windows-family vision software, the x64 build is the answer.

The OS fact settles the file format: a.dll is a Windows-format library, a Linux target loads a.so, and a real-time target needs a build from its own toolchain. Renaming a file converts nothing. The bitness fact settles the build configuration: check the host process, not just the OS, because a 64-bit OS happily runs 32-bit processes. The SDK bitness error behind a Python ImportError is the same rule biting on a PC. If you are still choosing the toolchain itself, embedded tool selection by target and build support applies the same target-first logic on the tool side.

The range below is x86 Intel from end to end — Intel N-series through Core i3, i5, i7 and Ultra processors, with 8 GB to 32 GB of memory across the series:

ComputersVision controllers

Vision computers and fanless industrial PCs

190 models · from $1,119.00
Vision controllersHikrobot MV-VC2140-128G40-1T VC2100 Vision Controller, N97, 8GB+128G SSD+ 1THDDMV-VC2140-128G40-1T
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
$1,679.00View part
Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
$2,419.00View part
Vision controllersHikrobot MV-VC4712-256G10-2TH Ultra 7 255H, 16G×2+256GSSD+2THDD, PCIe expansion, Without VM license keyMV-VC4712-256G10-2TH
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
$6,049.00 · quotedView and quote

How do I find every DLL my DLL depends on?

List the imports before the first transfer: your toolchain's import-listing tool prints every library your file asks for by name, and anything that is not part of the controller's base image travels with yours into the same folder — typically one or two SDK files plus the C runtime.

A typical first pass on a vision project: the listing shows 14 imports, 12 of them standard system files present on any Windows-family image, which leaves 2 files to ship — your SDK library and its runtime. Two files, one folder. Match versions, not just names: an older runtime copy found first on the search path produces a missing-entry-point error, and the stale-DLL walkthrough shows how to hunt the offender down.

Where do I put the DLL so the calling program actually finds it?

Put it where the loader looks first: the folder of the program that calls it. A call that names a bare file name resolves from the application folder and the system search path, so the reliable deploy sits next to the executable or names one explicit full path.

The loader resolves a bare name in a fixed order: application folder, system directories, then the search path. Embedded images rarely carry the search path your PC has, so the tail of that order is where deployments quietly die. Relative paths fail in a specific way: the vision runtime may start the program from a different working directory at boot than your test session used, so a path that worked on the bench fails unattended. The same search-order logic explains startup failures on a PC — diagnosing missing DLLs at application startup works the problem from that side.

What is the fastest way to prove the deployment before it reaches the line?

Five checks isolate every layer in order: matching byte counts, matching machine type, a minimal load test, a dependency audit on the controller itself, and a printed resolved path. Each check tests one layer, so whatever fails names its own cause and fix.

  1. Compare byte counts: note the size in bytes on the build machine and on the controller; the numbers must match exactly.
  2. Check the machine type in the file header — x64, x86 or ARM — against the target process before anything transfers.
  3. Run a minimal load test on the controller: a three-line host program that loads the library, calls one harmless export and frees it.
  4. Audit the dependencies on the target: every name from the import list must exist in the deploy folder or on the image.
  5. Print the path your external call resolves at startup and compare it, character by character, with the folder you copied to.
delta = bytes on PC − bytes on controller delta = 0 → bytes intact; the loader's complaint is genuine delta ≠ 0 → the transfer rewrote or truncated the file; resend in binary mode

A typical failure looks like this: the library shows 1,548,288 bytes on the build PC and 1,546,112 bytes on the controller. Delta = 1,548,288 − 1,546,112 = 2,176 bytes — the copy is short, so no loader argument matters yet. The session had run in text mode, which rewrote line-ending bytes inside the binary. A binary-mode resend gives 1,548,288 = 1,548,288, and the file that failed now loads. One number, one layer, one fix. When the runtime reports a numbered error instead of a plain message, walkthrough of DLL load-failure codes on vision targets maps the common codes to their layers.

When is the controller itself the reason it will not load?

Once bytes, build, dependencies and path all check out, four target-side limits remain: memory exhausted at load time, a filesystem that resets to its factory image on reboot, security software blocking unsigned code, or a 32-bit vendor runtime that cannot accept your 64-bit file.

Each has a test and a fix. Watch free memory while the vision software runs your real workload; a load that fails only at peak wants headroom, not settings. Power-cycle and check the file is still there; on images that reset at boot, deploy to the persistent partition or re-deploy as a startup step. If security policy blocks the load, sign the library or clear its folder through the plant's change process — never by disabling the protection. If the vendor vision runtime is 32-bit and cannot change, rebuild your library for 32-bit; the loader rule is absolute and fighting it wastes days. When an old target's stack cannot take your build at all, the keep-or-upgrade call mirrors the analog-camera decode-or-upgrade decision.

When streams and model files pile up, headroom is the spec that matters: the MV-VC5525-256G70-NN pairs a 12th-generation Core i5 with 32 GB of memory, a 256 GB SSD, PoE camera ports and eight built-in light channels.

Vision controllersHikrobot MV-VC5525-256G70-NN VC5000 Vision Controller, 12th-I5, 32GB+256G SSD, Supported PCIEMV-VC5525-256G70-NN
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
PoE
PoE camera ports
Light outputs
8 built-in channels
$4,479.00 · quotedView and quoteBuild a system with it

How do I keep the deployed DLL loading after a reboot or an update?

Treat the deployment as versioned state: one checksummed copy in the application folder, its size and hash recorded, and the five checks re-run after any controller software update, because updates replace runtimes, reset images and change search paths without asking.

Keep a small deployment record with the project: file name, byte count, hash, target controller, date. Add a version export to the library — one function that returns a build string — so any host can print exactly what is running. Archive the debug symbols matching the deployed hash; when a crash dump appears, symbols are the difference between a morning and a week. Change one variable per deployment: the library, or the runtime set, or the path, never two. More vision-controller guides cover the neighbouring failures: startup errors, network setup and SDK builds.

The decision, per case:

  • x86 Intel controller, Windows-family vision software, 64-bit host process → ship the x64 build plus its import list, into the executable's folder.
  • Transfer refuses with an I/O error → create the folder and fix account rights first; the library is not the problem.
  • Load fails naming a file → ship that exact file, same version, same folder.
  • Vendor runtime is 32-bit → rebuild the library for 32-bit; do not fight the loader.
  • Free memory runs out at peak → step up a controller class, not settings.

If you want a second opinion before the build ships, send the controller model and your dependency list through the contact page, or request a quote for multi-unit rollouts.

Questions

Can I put the DLL in the controller's system folder so the loader always finds it?

You can, but it is the weakest place to park code. A 64-bit process and a 32-bit process resolve system folders differently, so one copy cannot serve both, and a software update or factory reset can remove or replace it. Keep one copy in the application folder and fix the path in the call instead.

My dependency viewer shows names it cannot resolve — is the DLL broken?

Usually not. Modern Windows system libraries are API-set stubs, and older dependency viewers list them as unresolved or stop at that layer. Judge the non-system names instead: your own SDK files and the obvious runtimes. The five-check test on the controller is the verdict that matters.

Why is the file smaller on the controller after a transfer that reported success?

Text mode is the usual reason. A text-mode transfer rewrites line-ending bytes inside the file, so a binary lands a few thousand bytes short or long and the loader rejects it as invalid. Compare byte counts on both machines, switch the client to binary or image mode, and resend; when the counts match, the load question is real.

Is static linking a way to avoid DLL deployment altogether?

It removes the deployment problem entirely: the imports are baked in and there is no second file to lose. The cost is rebuilds — every fix recompiles the whole program — and two programs can no longer share one corrected library. For one controller running one fixed program, static linking is often the simpler choice; for a family of programs, keep the DLL.

Does FTP send my password in plain text on a plant network?

Yes — classic FTP sends user names and passwords unencrypted, so keep the controller on the machine network rather than the office LAN and use the device's secure-copy option where it offers one. The same segregation that protects the camera streams protects your deployed files.