Closed wbm0002 closed 2 weeks ago
I'm not sure I understand the question, if you've changed the C library substantially (for example you've changed the API surface of the C library), then you may need to write your own wrapper.
If the question is more about compiling the C library there are some notes here: https://github.com/libplctag/libplctag/blob/release/BUILD.md
Some standard questions from the Contributions guidance:
The API surface is the same, so I expect to be able to use the same wrapper. I'm not sure how I can use my modified plctag.dll with my C# program. Admittedly, I don't really know enough about the library to know what I'm doing wrong. So far, I have tried pointing my C# project at the libplctag.dll file generated by this project. That resulted in this error:
PS C:\Users\wbm\source\repos\libplctagtest\bin\Debug> .\libplctagtest.exe
Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'plctag': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at libplctag.NativeImport.NativeMethods.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout)
at libplctag.NativeImport.plctag.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout) in /_/src/libplctag.NativeImport/plctag.cs:line 45
at libplctag.Native.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout) in C:\Users\wbm\repos\libplctag.NET2\src\libplctag\Native.cs:line 19
at libplctag.Tag.Initialize() in C:\Users\wbm\repos\libplctag.NET2\src\libplctag\Tag.cs:line 637
at libplctag.Tag.InitializeIfRequired() in C:\Users\wbm\repos\libplctag.NET2\src\libplctag\Tag.cs:line 1042
at libplctag.Tag.Read() in C:\Users\wbm\repos\libplctag.NET2\src\libplctag\Tag.cs:line 732
at libplctag.Tag`2.Read() in C:\Users\wbm\repos\libplctag.NET2\src\libplctag\TagOfT.cs:line 185
at CSharpDotNetFramework.ExampleArray.Run(String ipAddress, String objectLocation, String writeValue, Boolean writeBool) in C:\Users\wbm\source\repos\libplctagtest\Array.cs:line 197
at Program.Main(String[] args) in C:\Users\wbm\source\repos\libplctagtest\Program.cs:line 88
PS C:\Users\wbm\source\repos\libplctagtest\bin\Debug> dir tlbimp.exe /s
Get-ChildItem: Cannot find path 'C:\Users\wbm\source\repos\libplctagtest\bin\Debug\tlbimp.exe' because it does not exist.
And attempting to add the plctag.dll file as a reference causes this error
Using NuGet to include libplctag in the project works fine, but I'd like to be able to use the version I have made modifications to.
Oh right - you should just be able to copy-paste your dll into the build output directory, over-writing the one that is currently in there. If you want to do it using the build system, you can set that add the dll file as a "Content" or "None" item, not a reference, which will copy it to the output directory.
Using the reference would be for managed Dlls (i.e. other .NET assemblies), not an unmanaged dll like the C library is.
Update to the latest prerelease if you can. The way the dlls were packaged has changed since the last production release
I am also having a similar issue to this. Currently, I am building a project with the libplctag NuGet package (latest prerelease) and a custom-built version of the libplctag C library. When I build out the .dll from my custom project and try to access it, I get the following issue:
Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'plctag': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at libplctag.NativeImport.NativeMethods.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout)
at libplctag.Native.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout) in /_/src/libplctag/Native.cs:line 19
at libplctag.Tag.Initialize() in /_/src/libplctag/Tag.cs:line 637
at libplctag.Tag.Read() in /_/src/libplctag/Tag.cs:line 734
at libplctag.Tag`2.Read() in /_/src/libplctag/TagOfT.cs:line 186
However, if I use the plctag.dll that is automatically built from the NuGet package, it works with no issues. Here is the version of the .dll I am talking about:
Debug Output:
X64 Folder:
For reference, when pulling from the libplctag C library github, this version of the plctag.dll is created, and when I switch out the libraries, it fails:
NOTE: This is on a fresh pull, no edits to the C library was made.
It works on my machine 😝
My steps to reproduce a succesful custom build of libplctag core, and include in a NET Framework project (Note that these steps would differ for .NETCore of .NET projects).
libplctag.NativeImport-v2.0.0-alpha.2
nuget package to the project. My system defaults to packages.config to track packages, but I believe it should also work with a <PackageReference>
style project.Program.cs
with the following:
using System;
using static libplctag.NativeImport.plctag;
namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { try { var result = plc_tag_decode_error(0); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine(e.Message); }
Console.Read(); // Press any key to continue
}
}
}
5. Run this with "Debug" and "Any CPU" configuration, and confirm that you get "PLCTAG_STATUS_OK" as output. If you get Exceptions at this point, something has gone wrong and it does not make sense to proceed.
6. Download [libplctag](https://github.com/libplctag/libplctag), and change [this](https://github.com/libplctag/libplctag/blob/release/src/lib/lib.c#L673) to return "Hello world"
7. Follow the [BUILD](https://github.com/libplctag/libplctag/blob/release/BUILD.md#visual-studio-community-2019-with-windows-10-1903) instructions to create your own copy of the C library with MSVC.
8. Copy `out\build\x64-Debug\bin_dist\plctag.dll` to `ConsoleApp1\bin\Debug\X64\plctag.dll`. If you're not running x64 bit, get the appropriate one instead.
**NOTE: I have found a bug with the `libplctag.NativeImport-v2.0.0-alpha.2` package at this point** - if you build your C# project again, it will copy the original plctag.dll in the output directory, overwriting your copy. I will fix this, but this is not the problem you are having, and will not prevent you from successfully using your own copy of the core C library.
10. Open up a terminal and run `ConsoleApp1.exe` - this will get around the above problem.
Instead of seeing "PLCTAG_STATUS_OK" you should now see "Hello world".
----
There are many things that need to go right for this to work, so when we are talking about this please include as much information as possible. System Information, Target platform, code listings, debug logs, [etc.](https://github.com/libplctag/libplctag.NET/blob/master/CONTRIBUTING.md#guidance-when-creating-an-issue)
I was able to get my modified C library working by copy-pasting the .dll into the build directory! But it doesn't work anywhere else :/ The app works as expected. The build directory contains only my executable, plctag.dll (C core), libplctag.dll (wrapper), and libplctag.NativeImport.dll. When I run a command on the machine that I built the app on, it works. But when I drop those files onto a USB and try on a different machine, I get the same error as above:
Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'plctag': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at libplctag.NativeImport.NativeMethods.plc_tag_create_ex(String lpString, callback_func_ex func, IntPtr userdata, Int32 timeout)
etc.
Per the requirements page you linked to, I've tried installing the C++ redistributables, but the problem persists. Why is it that on one machine, the executable can see the .dll, but on another, it cannot? Any further suggestions?
Are you able to add some extra details? System Information, Target platform, code listings, debug logs, etc.. If this is different for your two systems, then add the detail for both systems.
P/Invoke is the technology used to invoke unmanaged libraries, as you can see here: https://github.com/libplctag/libplctag.NET/blob/main/src/libplctag.NativeImport/NativeMethods.cs#L23
You can always upload a zip file of c# project - I imagine that a minimal repro would just be a Console application so it should be quite small.
@wbm0002 - have you had a chance to gather some more details?
I have made some modifications to the core libplctag C library on my local copy of the repository. I would like to compile the C# wrapper with these changes, but I am unsure of how to do this. Are there build instructions anywhere?