2014-02-27 55 views
3

我有一個C庫的結構定義下面的函數指針:C#調用C函數

struct SOME_STRUCT { 
    [...] 
    uint8_t(*printinfo) (SOME_STRUCT * ss, FILE * hFile); 
    [...] 
} 

此功能的一些數據寫入到文件處理HFILE,我想叫它來自C#。在C#中,我有:

[StructLayout(LayoutKind.Sequential)] 
public struct SomeStruct 
{ 
    [...] 
    public printinfoDelegate printinfo; 

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate byte printinfoDelegate(IntPtr ss, IntPtr hFile); 
    [...] 
} 

我用下面的代碼來調用該函數:

SomeStruct sStruct = [...]; 
String output; 

using (FileStream stream = new FileStream(tmpFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
{ 
    IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(sStruct)); 
    Marshal.StructureToPtr(sStruct, structPtr, false); 

    byte result = sStruct.printinfo(structPtr, stream.SafeFileHandle.DangerousGetHandle()); 

    stream.Seek(0, System.IO.SeekOrigin.Begin); 

    using (System.IO.StreamReader reader = new System.IO.StreamReader(stream)) 
    { 
     output = reader.ReadToEnd(); 
    } 
} 

,但我不能得到它的工作。我懷疑問題是我不能僅僅將文件流中的句柄作爲FILE *來傳遞。任何幫助將不勝感激...

+0

一個FILE * isn't只是處理。導入另一個C函數,該函數爲文件名提供一個FILE *(另一個函數再次關閉它)。 IE瀏覽器。 fopen和fclose的包裝。 – deviantfan

+0

您的懷疑是正確的,.net文件流與FILE *無關。 –

回答

2

.NET中的句柄指的是Win32 HANDLE(或HINSTANCE等等),例如,由CreateFile函數返回的那個。另一方面,A FILE *是C運行時庫的一部分,並且通過調用fopen函數返回。

所以如果你想使用那個需要FILE *參數的函數,那麼你也必須P /調用fopen方法,就像here一樣。

1

我相信有沒有辦法編組FileStream作爲文件*。如果你只需要C函數內的流,你可以通過callind fdopen()創建句柄。

0

您需要聲明fopenfclose的包裝。你需要的是這樣的:

public static class LegacyFileManager 
{ 
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
    public static extern IntPtr fopen(String filename, String mode); 
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
    public static extern Int32 fclose(IntPtr file); 
} 

然後在你的代碼:

IntPtr fileHandle = LegacyFileManager.fopen(tmpFileName, "r+"); 

// your logic here 

LegacyFileManager.fclose(fileHandle);