chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//            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 
{
    /// <summary>
    /// Attempt to load VISA libraries from the system
    /// </summary>
    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<byte> 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<byte> 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<string, IntPtr> 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<VisaFunctions.ViOpenDefaultRmDelegate>("viOpenDefaultRM");
                functions.ViFindRsrcRef = GetSymbol<VisaFunctions.ViFindRsrcDelegate>("viFindRsrc");
                functions.ViFindNextRef = GetSymbol<VisaFunctions.ViFindNextDelegate>("viFindNext");
                functions.ViParseRsrcRef = GetSymbol<VisaFunctions.ViParseRsrcDelegate>("viParseRsrc");
                functions.ViParseRsrcExRef = GetSymbol<VisaFunctions.ViParseRsrcExDelegate>("viParseRsrcEx");
                functions.ViOpenRef = GetSymbol<VisaFunctions.ViOpenDelegate>("viOpen");
                functions.ViCloseRef = GetSymbol<VisaFunctions.ViCloseDelegate>("viClose");
                functions.ViReadRef = viRead;
                viReadRef = GetSymbol<ViReadDelegate>("viRead");
                functions.ViWriteRef = viWrite;
                viWriteRef = GetSymbol<ViWriteDelegate>("viWrite");
                functions.ViReadStbRef = GetSymbol<VisaFunctions.ViReadStbDelegate>("viReadSTB");
                functions.ViClearRef = GetSymbol<VisaFunctions.ViClearDelegate>("viClear");
                functions.ViLockRef = GetSymbol<VisaFunctions.ViLockDelegate>("viLock");
                functions.ViUnlockRef = GetSymbol<VisaFunctions.ViUnlockDelegate>("viUnlock");
                functions.ViGetAttribute1Ref = GetSymbol<VisaFunctions.ViGetAttributeBDelegate>("viGetAttribute");
                functions.ViGetAttribute2Ref = GetSymbol<VisaFunctions.ViGetAttributeSbDelegate>("viGetAttribute");
                functions.ViGetAttribute3Ref = GetSymbol<VisaFunctions.ViGetAttributeIDelegate>("viGetAttribute");
                functions.ViSetAttribute1Ref = GetSymbol<VisaFunctions.ViSetAttributeBDelegate>("viSetAttribute");
                functions.ViSetAttribute2Ref = GetSymbol<VisaFunctions.ViSetAttributeIDelegate>("viSetAttribute");
                functions.ViStatusDescRef = GetSymbol<VisaFunctions.ViStatusDescDelegate>("viStatusDesc");
                functions.ViEnableEventRef = GetSymbol<VisaFunctions.ViEnableEventDelegate>("viEnableEvent");
                functions.ViDisableEventRef = GetSymbol<VisaFunctions.ViDisableEventDelegate>("viDisableEvent");
                functions.ViInstallHandlerRef = GetSymbol<VisaFunctions.ViInstallHandlerDelegate>("viInstallHandler");
                functions.ViUninstallHandlerRef = GetSymbol<VisaFunctions.ViUninstallHandlerDelegate>("viUninstallHandler");
                functions.ViWaitOnEventRef = GetSymbol<VisaFunctions.ViWaitOnEventDelegate>("viWaitOnEvent");
 
                return functions;
 
 
                T GetSymbol<T>(string str)
                {
                    return Marshal.GetDelegateForFunctionPointer<T>(loadSym(str));
                }
            }
            catch (Exception ex)
            {
                staticLog.Debug("External VISA library not loaded: {0}", ex);
                return null;
            }
        }
    }
}