dart-lang / sdk

The Dart SDK, including the VM, dart2js, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
9.99k stars 1.54k forks source link

dart ffi: error code 126 #51659

Open brizaldi opened 1 year ago

brizaldi commented 1 year ago

Hi, I got an error like this when trying to use ffi to load the librdkafka library.

Unhandled exception:
Invalid argument(s): Failed to load dynamic library 'C:\Projects\Dart\ffi_demo\library\librdkafka.dll': error code 126
#0      _open (dart:ffi-patch/ffi_dynamic_library_patch.dart:11:43)
#1      new DynamicLibrary.open (dart:ffi-patch/ffi_dynamic_library_patch.dart:22:12)
#2      main (file:///C:/Projects/Dart/ffi_demo\/bin/main.dart:26:36)
#3      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#4      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:192:26)

I obtained the librdkafka.dll file from NuGet. https://www.nuget.org/packages/librdkafka.redist/

and here's my code:

import 'dart:ffi' as ffi;
import 'dart:io' show Platform, Directory;

import 'package:path/path.dart' as path;

void main() {
  final libraryPath = path.join(Directory.current.path, 'library', 'librdkafka.dll');
  final dylib = ffi.DynamicLibrary.open(libraryPath);
}

Dart SDK version: 2.19.3 OS: Windows 11 22H2 build 22621.1344

alexmercerind commented 1 year ago

Not just the .DLL you're trying to load (using DynamicLibrary.open) needs to exist, but any of the .DLL files on which that .DLL itself depends upon need to be reachable. Safest approach is to place all of them in the executable's directory.

brizaldi commented 1 year ago

I have checked some of the dependencies required by librdkafka.dll using this tool:

And I have put all of them into one folder along with librdkafka.dll. However, I am still getting the same error.

dcharkes commented 1 year ago

Similar issue:

Can you check whether the file exists with File.existsSync() just to be sure the path-handling (separators etc) is correct?

I have checked some of the dependencies required by librdkafka.dll using this tool:

  • KERNEL32.dll
  • libcrypto-3-x64.dll
  • libcurl.dll
  • libssl-3-x64.dll
  • zlib1.dll
  • zstd.dll
  • Secur32.dll
  • WS2_32.dll
  • CRYPT32.dll

And I have put all of them into one folder along with librdkafka.dll. However, I am still getting the same error.

And this would indeed my second suggestion.

Did you get it to work?

brizaldi commented 1 year ago

Can you check whether the file exists with File.existsSync() just to be sure the path-handling (separators etc) is correct?

The path is correct since File.existsSync() returns true

Did you get it to work?

No, currently still stuck at loading the librdkafka library

dcharkes commented 1 year ago

You could try running dart.exe with the right arguments in the visual studio debugger.

brizaldi commented 1 year ago

I can load other DLLs fine, for example like the hello.dll from the official example or the libcurl.dll from above. However, when I try to load this librdkafka.dll, an error occurs.

Levi-Lesches commented 1 year ago

I'm having the same issue when compiling OpenCV.

I can use WSL to compile OpenCV to a .so library, run dart run ffigen to generate bindings and everything works in Dart. This, however, isn't ideal since WSL cannot access USB devices or webcams, which means I can't actually stream any video.

So I tried the process again on Windows. I used Visual Studio to generate a whole bunch of .dlls with cmake . in opencv\build\bin\Debug, but Dart gives an error 126 when I load one. This error does not occur when building other, simpler C projects on Windows.

I'm happy to provide more details if needed.

EDIT: I seemed to have fixed it by adding the folder with all the DLL's to my system path. I thought that wouldn't be needed since they were in the same folder together but since my terminal isn't in that folder, it didn't matter.

rinith commented 10 months ago

I'm having the same issue when compiling OpenCV.

I can use WSL to compile OpenCV to a .so library, run dart run ffigen to generate bindings and everything works in Dart. This, however, isn't ideal since WSL cannot access USB devices or webcams, which means I can't actually stream any video.

So I tried the process again on Windows. I used Visual Studio to generate a whole bunch of .dlls with cmake . in opencv\build\bin\Debug, but Dart gives an error 126 when I load one. This error does not occur when building other, simpler C projects on Windows.

I'm happy to provide more details if needed.

EDIT: I seemed to have fixed it by adding the folder with all the DLL's to my system path. I thought that wouldn't be needed since they were in the same folder together but since my terminal isn't in that folder, it didn't matter.

You had to add the folder which contain all dll's to system environment variables path??

Levi-Lesches commented 10 months ago

I believe so.

In Linux, there is an environment variable called LD_LIBRARY_PATH, which allows Linux to find .so files when they are linked at runtime. It's like the normal PATH variable on Windows, but exclusively for linked libraries.

Windows doesn't have another path variable like this (or at least, I didn't try one), so adding it to the system/user PATH is good enough. Of course, if your terminal is already in this folder, you don't need to add it, but in some cases you do:

myProject/
- bin/
  - project.exe
  - library.dll

If your terminal is in myProject, and you run bin\project.exe, then library.dll is not in your PATH or the current working directory (that would be myProject), so you need to add it to your PATH.

The way I get around it is by assuming my terminal is in myProject and making the code reference the .dll from there, so DynamicLibrary.open("bin/library.dll"). I also generate my .dlls in the root folder sometimes, when that's more convenient.