// Copyright Keysight Technologies 2012-2019 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.Linq; using System.Runtime.InteropServices; namespace OpenTap { /// /// Attempt to load VISA libraries from the system /// internal class VisaLibraryLoader : IVisaFunctionLoader { double IVisaFunctionLoader.Order => 10000; [DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string filename); [DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string procname); static TraceSource staticLog = Log.CreateSource("VisaLibraryLoader"); private unsafe delegate int ViReadDelegate(int vi, byte* buffer, int count, out int retCount); private ViReadDelegate viReadRef; private unsafe delegate int ViWriteDelegate(int vi, byte* buffer, int count, out int retCount); private ViWriteDelegate viWriteRef; public VisaLibraryLoader() { Functions = Load(); } public unsafe int viRead(int vi, ArraySegment buffer, int count, out int retCount) { if (buffer.Count < count) throw new ArgumentException("Amount of bytes requested is larger than the space available in buffer."); fixed (byte* p = &buffer.Array[buffer.Offset]) { return viReadRef(vi, p, count, out retCount); } } public unsafe int viWrite(int vi, ArraySegment buffer, int count, out int retCount) { if (buffer.Count < count) throw new ArgumentException("Amount of bytes requested to be written is larger than the space present in buffer."); fixed (byte* p = &buffer.Array[buffer.Offset]) { return viWriteRef(vi, p, count, out retCount); } } public VisaFunctions? Functions { get; } // Required by .NET to catch AccessViolationException. [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions] public VisaFunctions? Load() { try { Func loadSym; if (OperatingSystem.Current == OperatingSystem.Windows) { var libHandle = LoadLibrary("visa32.dll"); loadSym = name => GetProcAddress(libHandle, name); } else if (OperatingSystem.Current == OperatingSystem.Linux) { string[] paths = { "./libvisa32.so", "./libvisa.so", "libvisa32.so", "libvisa.so", "libiovisa.so", "./libiovisa.so" }; var libHandle = paths.Select(LibDl.Load).FirstOrDefault(x => x != IntPtr.Zero); loadSym = (name) => LibDl.Sym(libHandle, name); } else if (OperatingSystem.Current == OperatingSystem.MacOS) { string[] paths = { "./VISA", "/Library/Frameworks/VISA.framework/VISA" }; var libHandle = paths.Select(LibDl.Load).FirstOrDefault(x => x != IntPtr.Zero); loadSym = (name) => LibDl.Sym(libHandle, name); } else { staticLog.Debug("Unknown OS: {0}", OpenTap.OperatingSystem.Current); return null; } var functions = new VisaFunctions(); functions.ViOpenDefaultRmRef = GetSymbol("viOpenDefaultRM"); functions.ViFindRsrcRef = GetSymbol("viFindRsrc"); functions.ViFindNextRef = GetSymbol("viFindNext"); functions.ViParseRsrcRef = GetSymbol("viParseRsrc"); functions.ViParseRsrcExRef = GetSymbol("viParseRsrcEx"); functions.ViOpenRef = GetSymbol("viOpen"); functions.ViCloseRef = GetSymbol("viClose"); functions.ViReadRef = viRead; viReadRef = GetSymbol("viRead"); functions.ViWriteRef = viWrite; viWriteRef = GetSymbol("viWrite"); functions.ViReadStbRef = GetSymbol("viReadSTB"); functions.ViClearRef = GetSymbol("viClear"); functions.ViLockRef = GetSymbol("viLock"); functions.ViUnlockRef = GetSymbol("viUnlock"); functions.ViGetAttribute1Ref = GetSymbol("viGetAttribute"); functions.ViGetAttribute2Ref = GetSymbol("viGetAttribute"); functions.ViGetAttribute3Ref = GetSymbol("viGetAttribute"); functions.ViSetAttribute1Ref = GetSymbol("viSetAttribute"); functions.ViSetAttribute2Ref = GetSymbol("viSetAttribute"); functions.ViStatusDescRef = GetSymbol("viStatusDesc"); functions.ViEnableEventRef = GetSymbol("viEnableEvent"); functions.ViDisableEventRef = GetSymbol("viDisableEvent"); functions.ViInstallHandlerRef = GetSymbol("viInstallHandler"); functions.ViUninstallHandlerRef = GetSymbol("viUninstallHandler"); functions.ViWaitOnEventRef = GetSymbol("viWaitOnEvent"); return functions; T GetSymbol(string str) { return Marshal.GetDelegateForFunctionPointer(loadSym(str)); } } catch (Exception ex) { staticLog.Debug("External VISA library not loaded: {0}", ex); return null; } } } }