Pinvoke和Native Calls的Hello World

时间:2016-03-01 17:03:37

标签: visual-c++ win-universal-app

我正在尝试为Pinvoke和本地电话做一个非常基本的hello世界 我创建了一个包含2个项目的解决方案(一个用于dll,一个用于通用Windows应用程序) enter image description here

所以我最终得到了像这样的项目heirachy enter image description here

我的dll中有一个方法(文件NativeCalls.cpp):

#include "pch.h"
#include "NativeCalls.h"
#include <stdio.h>

MYAPI void print_line(const char* str) {
    printf("%s\n", str);
}

在我拥有NativeCalls.cs文件的C#方面

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;



namespace MSSurfaceHubMonitoring
{

    public static class NativeCalls
    {

        [DllImport("NativeCalls.dll")]
        private static extern void print_line(string str);

        public static void sayHelo()
        {
            print_line("Hello, PInvoke!");
        }
    }
}

此时我将构建并运行它,但得到一个无法找到dll的错误 enter image description here

但是我认为它是依赖而不是它自己的dll。我已经将dll的输出目录更改为运行UW应用程序的根目录(\ bin \ x86),所以它确实应该找到它。就像我说的那样,我认为它是依赖关系,而不是实际的dll。

这是我在Dependency Walker中看到的内容 enter image description here 但是我已经安装了所有可以获得的c ++包,所以我不明白如何获取缺少的依赖项。此外,这只是一个问候世界,为什么我需要所有这些库。

FYI 我的dll项目没有被UW app引用。我不确定是否需要?我不这么认为,因为这是一个运行时的东西,所以只要dll在那里就应该找到并阅读它。但无论我是否尝试将项目添加为参考,我都会收到此错误: enter image description here

1 个答案:

答案 0 :(得分:0)

对我来说最大的帮助就是找到这些方法声明(甚至不在课堂上)

extern "C" {
    __declspec(dllexport) int getPageSize()
    {
        SYSTEM_INFO siSysInfo;
        GetSystemInfo(&siSysInfo);
        return siSysInfo.dwPageSize;
    }
}

extern "C" {
    __declspec(dllexport) Windows::Foundation::Collections::IMap<Platform::String^, int> ^getSystemInfo()
    {
        SYSTEM_INFO siSysInfo;
        GetSystemInfo(&siSysInfo);

        IMap<String^, int> ^ret =
            ref new Platform::Collections::Map<String^, int>;
        ret->Insert("oemId", siSysInfo.dwOemId);
        ret->Insert("cpuCount", siSysInfo.dwNumberOfProcessors);
        ret->Insert("pageSize", siSysInfo.dwPageSize);
        ret->Insert("processorType", siSysInfo.dwProcessorType);
        ret->Insert("maxApplicationAddress", siSysInfo.lpMinimumApplicationAddress);
        ret->Insert("minApplicationAddress", siSysInfo.lpMaximumApplicationAddress);
        ret->Insert("activeProcessorMask", siSysInfo.dwActiveProcessorMask);
        return ret;
    }

但最后我正在为我不需要的东西创建包装器。在c#中,您可以直接调用本机方法,而无需单独的dll或组件项目。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;


namespace Monitoring
{

    public static class NativeCallsWrapper
    {
        private static SYSTEM_INFO sysInfo = new SYSTEM_INFO();
        private static MEMORYSTATUSEX mem = new MEMORYSTATUSEX();

        [DllImport("kernel32.dll", SetLastError = false)]
        public static extern void GetSystemInfo([In, Out] SYSTEM_INFO Info);

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);

        static NativeCallsWrapper()
        {
            GetSystemInfo(sysInfo);
            GlobalMemoryStatusEx(mem);
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct SYSTEM_INFO_UNION

        {

            [FieldOffset(0)]
            public UInt32 OemId;
            [FieldOffset(0)]
            public UInt16 ProcessorArchitecture;
            [FieldOffset(2)]
            public UInt16 Reserved;
        }

        public struct SYSTEM_INFO

        {

            public SYSTEM_INFO_UNION CpuInfo;
            public UInt32 PageSize;
            public UInt32 MinimumApplicationAddress;
            public UInt32 MaximumApplicationAddress;
            public UInt32 ActiveProcessorMask;
            public UInt32 NumberOfProcessors;
            public UInt32 ProcessorType;
            public UInt32 AllocationGranularity;
            public UInt16 ProcessorLevel;
            public UInt16 ProcessorRevision;
        }

        [StructLayout(LayoutKind.Sequential)]
        public class MEMORYSTATUSEX
        {
            public uint dwLength;
            public uint dwMemoryLoad;
            public ulong ullTotalPhys;
            public ulong ullAvailPhys;
            public ulong ullTotalPageFile;
            public ulong ullAvailPageFile;
            public ulong ullTotalVirtual;
            public ulong ullAvailVirtual;
            public ulong ullAvailExtendedVirtual;
            public MEMORYSTATUSEX()
            {
                this.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
            }
        }

        public static GeneralStatistics getGeneralStatistics()
        {
            GeneralStatistics generalStatistics = new GeneralStatistics();
            generalStatistics.numberOfProcesses = (int)sysInfo.NumberOfProcessors;
            generalStatistics.memoryTotal = mem.ullTotalPhys / 1048;
            generalStatistics.memoryInUse = (mem.ullTotalPhys - mem.ullAvailPhys) / 1048;
            return generalStatistics;
        }
    }
}