翻译 Delphi 导出到 C#/Vb.Net
Translate Delphi export to C#/Vb.Net
我正在编写 Subtitle Workshop 库的简单包装器,但我无法将此 Delphi 导出转换为 C# 或 Vb.Net:
procedure GetSubtitleText(Time: Integer; Text: {$IFDEF UTF8}PWideChar{$ELSE}PChar{$ENDIF}; var BufferLen: Integer); stdcall;
var
FText : {$IFDEF UTF8}WideString{$ELSE}String{$ENDIF};
begin
FText := DisplaySubtitle(Subtitles, Time);
if BufferLen > 0 then
{$IFDEF UTF8}
// Text := Copy(FText, 1, BufferLen)
Text := StringToWideChar(FText, Text, BufferLen)
{$ELSE}
StrLCopy(Text, PChar(FText), BufferLen)
{$ENDIF}
else
BufferLen := Length(FText);
end;
我不明白如何翻译 Text
参数的条件。
这是我所做的:
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleText", CharSet:=CharSet.Ansi)>
Friend Shared Sub GetSubtitleText(
<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef bufferLength As Integer
)
End Sub
它似乎按预期工作,但是,我想确保我写的正确。
只要编译 Delphi 代码时未定义 UTF8
,您的翻译就可以了。如果定义了 UTF8
,那么您需要编组为 LPWStr
。而且我必须假设 Delphi 代码是使用 Delphi 的 ANSI 版本编译的,因此 PChar
映射到 PAnsiChar
。如果您尝试使用 Delphi 2009 或更高版本进行编译,Delphi 代码将被完全破坏。
如果您使用明确的 MarshalAs
属性明确标记每个参数,那么指定 CharSet.Ansi
没有多大意义。
Delphi 代码很奇怪。作者好像不知道UTF-8和UTF-16的区别。在 Delphi 中,PWideChar
和 WideString
是 UTF-16 编码的。对 StrLCopy
的调用传递了错误的缓冲区长度,由于该 RTL 函数的设计非常糟糕,它应该传递 BufferLen - 1
。该代码还应将 BufferLen
设置为复制的字符数,但实际上没有。
您可以在 .net 代码中解决这个问题。我将编写 C#,因为那是我所知道的。我相信你会明白的:
int len = 0;
GetSubtitleText(time, null, len);
StringBuilder sb = new StringBuilder(len);
len++; // work around poor design/use of StrLCopy
GetSubtitleText(time, sb, len);
从表面上看,我对这个 Delphi 代码有些怀疑。你应该保持警惕。至少你有它的源代码!
我只是想分享我在Vb.Net中写的P/Invokes:
' ***********************************************************************
' Author : Elektro
' Modified : 18-March-2016
' ***********************************************************************
#Region " Public Members Summary "
#Region " Functions "
' OpenFile(String, Single, Integer, Boolean, Boolean) As Boolean
' SaveFile(String, Integer, Single, Integer, Integer) As Boolean
' GetPlaybackDelay() As Integer
' SetAbsoluteDelay(Integer, Integer, Integer) As Boolean
' GetFormatIndex(String) As Integer
' GetFormatInformation(Integer, StringBuilder, StringBuilder, Integer, Integer) As Boolean
' GetSubtitleLineCount() As Integer
' GetSubtitleLine(Integer, Integer, Integer, StringBuilder, Integer) As Boolean
' AddSubtitleLine(Integer, Integer, String) As Integer
' InsertSubtitleLine(Integer, Integer, Integer, String) As Boolean
' DeleteSubtitleLine(Integer) As Boolean
' CreateNewSubtitleLine()
#End Region
#Region " Methods "
' ClearSubtitleLines()
' CloseFile()
' GetCurrentFormatName(StringBuilder, Integer, Integer)
' GetFormatName(Integer, StringBuilder, Integer)
' GetSubtitleText(Integer, StringBuilder, Integer)
' SetPlaybackDelay(Integer)
#End Region
#End Region
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
Imports System
Imports System.Linq
Imports System.Runtime.InteropServices
Imports System.Security
#End Region
#Region " P/Invoke "
Namespace SubtitleWorkshop.Interop
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Platform Invocation methods (P/Invoke), access unmanaged code.
''' <para></para>
''' This class suppresses stack walks for unmanaged code permission.
''' <see cref="System.Security.SuppressUnmanagedCodeSecurityAttribute"/> is applied to this class.
''' <para></para>
''' This class is for methods that are safe for anyone to call.
''' <para></para>
''' Callers of these methods are not required to perform a full security review to make sure that the
''' usage is secure because the methods are harmless for any caller.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="http://msdn.microsoft.com/en-us/library/ms182161.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
Friend NotInheritable Class SafeNativeMethods
#Region " Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Opens the specified subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="filepath">
''' The source subtitle filepath.
''' </param>
'''
''' <param name="fps">
''' The subtitle FPS.
''' </param>
'''
''' <param name="formatIndex">
''' The subtitle format index.
''' </param>
'''
''' <param name="append">
''' If <see langword="True"/>, appends to the end of the subtitle file.
''' </param>
'''
''' <param name="reCalcTimeValues">
''' If <see langword="True"/>, recalculates the time values of the subtitle.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the specified subtitle file was open successfully, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="LoadSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function OpenFile(<MarshalAs(UnmanagedType.LPStr)> ByVal filepath As String,
<MarshalAs(UnmanagedType.R4)> ByVal fps As Single,
<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.Bool)> ByVal append As Boolean,
<MarshalAs(UnmanagedType.Bool)> ByVal reCalcTimeValues As Boolean
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Closes the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="CloseSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub CloseFile()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Saves (or converts) the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="filepath">
''' The target subtitle filepath.
''' </param>
'''
''' <param name="formatIndex">
''' The target subtitle format.
''' </param>
'''
''' <param name="fps">
''' The target subtitle FPS.
''' </param>
'''
''' <param name="fromIndex">
''' The starting index to copy from the source subtitle lines.
''' </param>
'''
''' <param name="toIndex">
''' The ending index to copy from the source subtitle lines.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SaveSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function SaveFile(<MarshalAs(UnmanagedType.LPStr)> ByVal filepath As String,
<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.R4)> ByVal fps As Single,
<MarshalAs(UnmanagedType.I4)> ByVal fromIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal toIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the format index of the specified subtitle format name.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatName">
''' The name of the subtitle format.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The subtitle format index.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatIndex", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetFormatIndex(<MarshalAs(UnmanagedType.LPStr)> ByVal formatName As String
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the format name of the specified subtitle format index.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatIndex">
''' The index of the subtitle format.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle format name.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatName", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetFormatName(<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets information of the specified subtitle format index.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatIndex">
''' The index of the subtitle format.
''' </param>
'''
''' <param name="bufferDescription">
''' The string buffer to store the the subtitle format description.
''' </param>
'''
''' <param name="bufferExtensions">
''' The string buffer to store the the subtitle format extensions.
''' </param>
'''
''' <param name="refBufferDescriptionLength">
''' A by-reference variable that indicates the length of <paramref name="bufferDescription"/>.
''' </param>
'''
''' <param name="refBufferExtensionsLength">
''' A by-reference variable that indicates the length of <paramref name="bufferExtensions"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatInformation", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetFormatInformation(<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal bufferDescription As StringBuilder,
<MarshalAs(UnmanagedType.LPStr)> ByVal bufferExtensions As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferDescriptionLength As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferExtensionsLength As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle format name of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="buffer">
''' The string buffer to store the the subtitle format name.
''' </param>
'''
''' <param name="refIndex">
''' A by-reference variable that stores the subtitle format name.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetCurrentFormat", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetCurrentFormatName(<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the line count of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The line count.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleCount", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetSubtitleLineCount(
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle text at the specified time on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The time, in milliseconds.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle text.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleText", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetSubtitleText(<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle text at the specified line of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The line index.
''' </param>
'''
''' <param name="refStartTime">
''' A by-reference variable that stores the starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="refEndTime">
''' A by-reference variable that stores the ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle text.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refStartTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refEndTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sets an absolute delay on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The delay, in milliseconds.
''' </param>
'''
''' <param name="fromLineIndex">
''' The starting subtitle line index.
''' </param>
'''
''' <param name="toLineIndex">
''' The ending subtitle line index.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SetAbsoluteDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function SetAbsoluteDelay(
<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal fromLineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal toLineIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the playback delay of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The playback delay, in milliseconds.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetPlaybackDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetPlaybackDelay(
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sets a playback delay on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The playback delay, in milliseconds.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SetPlaybackDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub SetPlaybackDelay(<MarshalAs(UnmanagedType.I4)> ByVal time As Integer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Adds a subtitle line at the specified time in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="startTime">
''' The starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="endTime">
''' The ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="text">
''' The subtitle text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
'''
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="AddSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function AddSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal startTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal endTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As String
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Adds a subtitle line at the specified time in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The index of the line where to insert the subtitle line.
''' </param>
'''
''' <param name="startTime">
''' The starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="endTime">
''' The ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="text">
''' The subtitle text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="InsertSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function InsertSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal endTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal startTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As String
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Removes a subtitle line in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The index of the subtitle line to remove.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="DeleteSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function DeleteSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Clears all the subtitle lines in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="ClearSubtitles", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub ClearSubtitleLines()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Create a new subtitle.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="CreateNewSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub CreateNewSubtitleLine()
End Sub
#End Region
End Class
End Namespace
#End Region
我正在编写 Subtitle Workshop 库的简单包装器,但我无法将此 Delphi 导出转换为 C# 或 Vb.Net:
procedure GetSubtitleText(Time: Integer; Text: {$IFDEF UTF8}PWideChar{$ELSE}PChar{$ENDIF}; var BufferLen: Integer); stdcall;
var
FText : {$IFDEF UTF8}WideString{$ELSE}String{$ENDIF};
begin
FText := DisplaySubtitle(Subtitles, Time);
if BufferLen > 0 then
{$IFDEF UTF8}
// Text := Copy(FText, 1, BufferLen)
Text := StringToWideChar(FText, Text, BufferLen)
{$ELSE}
StrLCopy(Text, PChar(FText), BufferLen)
{$ENDIF}
else
BufferLen := Length(FText);
end;
我不明白如何翻译 Text
参数的条件。
这是我所做的:
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleText", CharSet:=CharSet.Ansi)>
Friend Shared Sub GetSubtitleText(
<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef bufferLength As Integer
)
End Sub
它似乎按预期工作,但是,我想确保我写的正确。
只要编译 Delphi 代码时未定义 UTF8
,您的翻译就可以了。如果定义了 UTF8
,那么您需要编组为 LPWStr
。而且我必须假设 Delphi 代码是使用 Delphi 的 ANSI 版本编译的,因此 PChar
映射到 PAnsiChar
。如果您尝试使用 Delphi 2009 或更高版本进行编译,Delphi 代码将被完全破坏。
如果您使用明确的 MarshalAs
属性明确标记每个参数,那么指定 CharSet.Ansi
没有多大意义。
Delphi 代码很奇怪。作者好像不知道UTF-8和UTF-16的区别。在 Delphi 中,PWideChar
和 WideString
是 UTF-16 编码的。对 StrLCopy
的调用传递了错误的缓冲区长度,由于该 RTL 函数的设计非常糟糕,它应该传递 BufferLen - 1
。该代码还应将 BufferLen
设置为复制的字符数,但实际上没有。
您可以在 .net 代码中解决这个问题。我将编写 C#,因为那是我所知道的。我相信你会明白的:
int len = 0;
GetSubtitleText(time, null, len);
StringBuilder sb = new StringBuilder(len);
len++; // work around poor design/use of StrLCopy
GetSubtitleText(time, sb, len);
从表面上看,我对这个 Delphi 代码有些怀疑。你应该保持警惕。至少你有它的源代码!
我只是想分享我在Vb.Net中写的P/Invokes:
' ***********************************************************************
' Author : Elektro
' Modified : 18-March-2016
' ***********************************************************************
#Region " Public Members Summary "
#Region " Functions "
' OpenFile(String, Single, Integer, Boolean, Boolean) As Boolean
' SaveFile(String, Integer, Single, Integer, Integer) As Boolean
' GetPlaybackDelay() As Integer
' SetAbsoluteDelay(Integer, Integer, Integer) As Boolean
' GetFormatIndex(String) As Integer
' GetFormatInformation(Integer, StringBuilder, StringBuilder, Integer, Integer) As Boolean
' GetSubtitleLineCount() As Integer
' GetSubtitleLine(Integer, Integer, Integer, StringBuilder, Integer) As Boolean
' AddSubtitleLine(Integer, Integer, String) As Integer
' InsertSubtitleLine(Integer, Integer, Integer, String) As Boolean
' DeleteSubtitleLine(Integer) As Boolean
' CreateNewSubtitleLine()
#End Region
#Region " Methods "
' ClearSubtitleLines()
' CloseFile()
' GetCurrentFormatName(StringBuilder, Integer, Integer)
' GetFormatName(Integer, StringBuilder, Integer)
' GetSubtitleText(Integer, StringBuilder, Integer)
' SetPlaybackDelay(Integer)
#End Region
#End Region
#Region " Option Statements "
Option Strict On
Option Explicit On
Option Infer Off
#End Region
#Region " Imports "
Imports System
Imports System.Linq
Imports System.Runtime.InteropServices
Imports System.Security
#End Region
#Region " P/Invoke "
Namespace SubtitleWorkshop.Interop
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Platform Invocation methods (P/Invoke), access unmanaged code.
''' <para></para>
''' This class suppresses stack walks for unmanaged code permission.
''' <see cref="System.Security.SuppressUnmanagedCodeSecurityAttribute"/> is applied to this class.
''' <para></para>
''' This class is for methods that are safe for anyone to call.
''' <para></para>
''' Callers of these methods are not required to perform a full security review to make sure that the
''' usage is secure because the methods are harmless for any caller.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="http://msdn.microsoft.com/en-us/library/ms182161.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
Friend NotInheritable Class SafeNativeMethods
#Region " Methods "
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Opens the specified subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="filepath">
''' The source subtitle filepath.
''' </param>
'''
''' <param name="fps">
''' The subtitle FPS.
''' </param>
'''
''' <param name="formatIndex">
''' The subtitle format index.
''' </param>
'''
''' <param name="append">
''' If <see langword="True"/>, appends to the end of the subtitle file.
''' </param>
'''
''' <param name="reCalcTimeValues">
''' If <see langword="True"/>, recalculates the time values of the subtitle.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the specified subtitle file was open successfully, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="LoadSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function OpenFile(<MarshalAs(UnmanagedType.LPStr)> ByVal filepath As String,
<MarshalAs(UnmanagedType.R4)> ByVal fps As Single,
<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.Bool)> ByVal append As Boolean,
<MarshalAs(UnmanagedType.Bool)> ByVal reCalcTimeValues As Boolean
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Closes the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="CloseSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub CloseFile()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Saves (or converts) the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="filepath">
''' The target subtitle filepath.
''' </param>
'''
''' <param name="formatIndex">
''' The target subtitle format.
''' </param>
'''
''' <param name="fps">
''' The target subtitle FPS.
''' </param>
'''
''' <param name="fromIndex">
''' The starting index to copy from the source subtitle lines.
''' </param>
'''
''' <param name="toIndex">
''' The ending index to copy from the source subtitle lines.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SaveSubtitleFile", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function SaveFile(<MarshalAs(UnmanagedType.LPStr)> ByVal filepath As String,
<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.R4)> ByVal fps As Single,
<MarshalAs(UnmanagedType.I4)> ByVal fromIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal toIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the format index of the specified subtitle format name.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatName">
''' The name of the subtitle format.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The subtitle format index.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatIndex", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetFormatIndex(<MarshalAs(UnmanagedType.LPStr)> ByVal formatName As String
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the format name of the specified subtitle format index.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatIndex">
''' The index of the subtitle format.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle format name.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatName", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetFormatName(<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets information of the specified subtitle format index.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="formatIndex">
''' The index of the subtitle format.
''' </param>
'''
''' <param name="bufferDescription">
''' The string buffer to store the the subtitle format description.
''' </param>
'''
''' <param name="bufferExtensions">
''' The string buffer to store the the subtitle format extensions.
''' </param>
'''
''' <param name="refBufferDescriptionLength">
''' A by-reference variable that indicates the length of <paramref name="bufferDescription"/>.
''' </param>
'''
''' <param name="refBufferExtensionsLength">
''' A by-reference variable that indicates the length of <paramref name="bufferExtensions"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetFormatInformation", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetFormatInformation(<MarshalAs(UnmanagedType.I4)> ByVal formatIndex As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal bufferDescription As StringBuilder,
<MarshalAs(UnmanagedType.LPStr)> ByVal bufferExtensions As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferDescriptionLength As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferExtensionsLength As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle format name of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="buffer">
''' The string buffer to store the the subtitle format name.
''' </param>
'''
''' <param name="refIndex">
''' A by-reference variable that stores the subtitle format name.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetCurrentFormat", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetCurrentFormatName(<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the line count of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The line count.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleCount", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetSubtitleLineCount(
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle text at the specified time on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The time, in milliseconds.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle text.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitleText", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub GetSubtitleText(<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the subtitle text at the specified line of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The line index.
''' </param>
'''
''' <param name="refStartTime">
''' A by-reference variable that stores the starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="refEndTime">
''' A by-reference variable that stores the ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="buffer">
''' The string buffer to store the the subtitle text.
''' </param>
'''
''' <param name="refBufferLength">
''' A by-reference variable that indicates the length of <paramref name="buffer"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refStartTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByRef refEndTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal buffer As StringBuilder,
<MarshalAs(UnmanagedType.I4)> ByRef refBufferLength As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sets an absolute delay on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The delay, in milliseconds.
''' </param>
'''
''' <param name="fromLineIndex">
''' The starting subtitle line index.
''' </param>
'''
''' <param name="toLineIndex">
''' The ending subtitle line index.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SetAbsoluteDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function SetAbsoluteDelay(
<MarshalAs(UnmanagedType.I4)> ByVal time As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal fromLineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal toLineIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets the playback delay of the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The playback delay, in milliseconds.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="GetPlaybackDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function GetPlaybackDelay(
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Sets a playback delay on the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="time">
''' The playback delay, in milliseconds.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="SetPlaybackDelay", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub SetPlaybackDelay(<MarshalAs(UnmanagedType.I4)> ByVal time As Integer)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Adds a subtitle line at the specified time in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="startTime">
''' The starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="endTime">
''' The ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="text">
''' The subtitle text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
'''
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="AddSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function AddSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal startTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal endTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As String
) As <MarshalAs(UnmanagedType.I4)> Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Adds a subtitle line at the specified time in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The index of the line where to insert the subtitle line.
''' </param>
'''
''' <param name="startTime">
''' The starting subtitle time, in milliseconds.
''' </param>
'''
''' <param name="endTime">
''' The ending subtitle time, in milliseconds.
''' </param>
'''
''' <param name="text">
''' The subtitle text.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="InsertSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function InsertSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal endTime As Integer,
<MarshalAs(UnmanagedType.I4)> ByVal startTime As Integer,
<MarshalAs(UnmanagedType.LPStr)> ByVal text As String
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Removes a subtitle line in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <param name="lineIndex">
''' The index of the subtitle line to remove.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' <see langword="True"/> if the operation success, otherwise, <see langword="False"/>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="DeleteSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Function DeleteSubtitleLine(<MarshalAs(UnmanagedType.I4)> ByVal lineIndex As Integer
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Clears all the subtitle lines in the current subtitle file.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="ClearSubtitles", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub ClearSubtitleLines()
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Create a new subtitle.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<SuppressUnmanagedCodeSecurity>
<DllImport("SubtitleAPI.dll", EntryPoint:="CreateNewSubtitle", SetLastError:=False, CharSet:=CharSet.Ansi)>
Friend Shared Sub CreateNewSubtitleLine()
End Sub
#End Region
End Class
End Namespace
#End Region