开发者

Bind to an exported value by pinvoke

开发者 https://www.devze.com 2023-04-07 05:21 出处:网络
I have a dll that exports not only functions, but also values. The dll I\'m interested in is from the R Project (http://www.r-project.org/),开发者_开发百科 it\'s in the R.dll that contains the r langu

I have a dll that exports not only functions, but also values. The dll I'm interested in is from the R Project (http://www.r-project.org/),开发者_开发百科 it's in the R.dll that contains the r language runtime. The declaration in the header file is:

LibExtern SEXP     R_GlobalEnv;

And when when I run dumpbin /exports I can see:

    194   C1 00326C08 R_GlobalEnv

But I can't seem to find any examples of how to bind such a value from C# or F#. Can anyone enlightenment me to how I might get a reference to it?


I don't known if there is a way directly from C# or F#. But I think that a C++/CLI wrapper should work.


After Nick pointed me in the direction of R.NET I was able to look and see how they solved this problem.

First they use the win32 api to load the library (or equivalent on other platforms):

#if MAC || LINUX
        private static IntPtr LoadLibrary(string filename)
        {
            const int RTLD_LAZY = 0x1;

            if (filename.StartsWith("/"))
            {
                return dlopen(filename, RTLD_LAZY);
            }

            string[] searchPaths = (System.Environment.GetEnvironmentVariable(LibraryPath, EnvironmentVariableTarget.Process) ?? "").Split(Path.PathSeparator);
            foreach (string directory in searchPaths)
            {
                string path = Path.Combine(directory, filename);
                if (File.Exists(path))
                {
                    return dlopen(path, RTLD_LAZY);
                }
            }
            return IntPtr.Zero;
        }

        [DllImport(DynamicLoadingLibraryName)]
        private static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPStr)] string filename, int flag);
#elif WINDOWS
        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);

Then they use get GetProcAddress function from kernel32.dll (or equivalent on other platforms) to get the actual address of the variable:

#if MAC
        [DllImport("libdl.dylib", EntryPoint = "dlsym")]
#elif LINUX
        [DllImport("libdl.so", EntryPoint = "dlsym")]
#elif WINDOWS
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
#endif
        private static extern IntPtr GetSymbolPointer(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string symbol);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号