1

我正在尝试访问 Nikon 图像 SDK(感兴趣的人请参阅:1)以在程序中实现对 *.nef 文件的访问。我被困在 dll 的返回码上,它应该被解释为“无效参数”,而且我已经没有想法了。

是的,我知道机会,有人正在使用这个 dll 是稀疏的,但我宁愿寻找“写作”/“思考”错误......我还在学习(所以请原谅任何错误使用的术语等。 ..) 并且出于这个原因,这是一个“更长”的帖子(我这边的一些“大声思考”;-))

1.) dll 有一个入口函数,您可以在其中传递一个标识符和一个结构体作为参数。标识符代表特定命令(如打开、关闭等....)。该结构用于与相机进行数据交换。

2.)我确实将所有东西放在一起并且可以工作(因为我得到了一个“返回码”),但我无法弄清楚返回码的原因(也许某些数据类型不兼容?)

所以首先是“C++”部分:

c++函数定义:

extern "C" unsigned long __declspec(dllexport) WINAPI Nkfl_Entry(unsigned long ulCommand, void* pParam );

这是stdcall,所以我确实需要担心dllimport的任何其他选项,因为usigned long(c ++)对应于uint(c#)我得到两个uint,一个“out”和一个“in”......

C++结构定义:

typedef struct tagNkflLibraryParam
{
     unsigned long  ulSize;         // Size of structure
     unsigned long  ulVersion;      // Version
     unsigned long  ulVMMemorySize;     // Size of vertual memory
     NkflPtr* pNkflPtr;                 // Pointer of StratoObject
     unsigned char  VMFileInfo[ MAX_PATH ]; // Swap file info
} NkflLibraryParam, *NkflLibraryPtr;

所以我确实需要传递3次uint,一个指向“StratoObject”的指针((1。)文档说“typedef void * NkflPtr”所以这“只是”一个void *指针2。)文档说如果这是零它将被 sdk 填充)最后一个字节(因为 unsigned char(c++) 对应于 byte(c#))。

所以第一个问题:这是正确的吗?

然后转到“编码部分”:

c#结构定义:

namespace NikonStruct
{
    [StructLayout(LayoutKind.Sequential)]
    public struct NkflLibraryParam
    {
        public uint ulSize;          // size of the NkflLibraryParam structure
        public uint ulVersion;       // version number of the interface specification
        public uint ulVMMMemorySize; // upper limit of the physical memory that can be used
        public IntPtr pNkflPtr;      // pointer to the StratoManager object
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
        public byte[] VMFileInfo;      // swap file information
    }
}

现在这应该对应于我上面的定义......

c#程序类:

class Program
{
    public enum eNkflCommand : int
    {
        kNkfl_Cmd_OpenLibrary = 1,
        kNkfl_Cmd_CloseLibrary = 2,
    };

    [DllImport("NkImgSDK.dll", EntryPoint = "Nkfl_Entry")]
    public static extern uint kNkfl_Cmd_OpenLibrary(eNkflCommand ulCommand, ref NikonStruct.NkflLibraryParam data);

    [DllImport("NkImgSDK.dll", EntryPoint = "Nkfl_Entry")]
    public static extern uint kNkfl_Cmd_CloseLibrary(eNkflCommand ulCommand, IntPtr close);

    static void Main(string[] args)
    {
        try
        {
            // specify return value of entry function
            uint result1, result2;

            /// call the kNkfl_Cmd_OpenLibrary Function 
            // generate data structure, which is used to communicate with kNkfl_Cmd_OpenLibrary function
            NikonStruct.NkflLibraryParam _NkflLibraryParam = new NikonStruct.NkflLibraryParam();
            // fill the fields of _NkflLibraryParam structure for kNkfl_Cmd_OpenLibrary function
            _NkflLibraryParam.ulVersion = 16777216;
            _NkflLibraryParam.ulSize = ((uint)Marshal.SizeOf(_NkflLibraryParam)); ;
            // call the entry function with parameters for kNkfl_Cmd_OpenLibrary 
            result1 = kNkfl_Cmd_OpenLibrary(eNkflCommand.kNkfl_Cmd_OpenLibrary, ref _NkflLibraryParam);

            Console.WriteLine(result1);

            /// call the kNkfl_Cmd_CloseLibrary Function
            result2 = kNkfl_Cmd_CloseLibrary(eNkflCommand.kNkfl_Cmd_CloseLibrary, IntPtr.Zero);

            Console.WriteLine(result2);
        }
        catch
        {
            string errorMsg = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message;
            throw new ArgumentException(errorMsg);
        }
    }
}

所以这里没有什么特别的:

  • eNkflCommand 来自文档
  • 该结构是通过引用传递的,所以参考...
  • “关闭”函数需要“空指针”(根据文档)
  • ulVersion 为 0x01000000 (根据文档)
  • 未设置所有其他结构值(如果我正确理解了 clr 文档,则默认为零)

如前所述编译和运行,但 result1 返回错误的“状态代码”,如前所述,转换为“无效参数”。

任何帮助表示赞赏....

4

1 回答 1

2

找到了:

永远不要相信软件开发人员的文档:实际上缺少一个参数(未在文档中声明但在另一个头定义文件中,该文件位于 sdk 包的另一个子目录中......)

所以实际上c#中的结构定义应该是:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct struktur
{
    public uint ulSize;          // size of the NkflLibraryParam structure
    public uint ulVersion;       // version number of the interface specification
    public uint ulVMMMemorySize; // upper limit of the physical memory that can be used
    public IntPtr pNkflPtr;      // pointer to the StratoManager object
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
    public byte[] VMFileInfo;      // swap file information
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)]
    public byte[] DefProfPath; // <- this one is not included in the doc of NIKON (I still don't now what this should hold but it works if it's empty...)
}

感谢 jszigeti 和 DavidHeffernan 的尝试...

于 2013-06-15T08:15:54.730 回答