如何获得工作的 x64 THREADSAFE Ghostscript DLL
How to get a working x64 THREADSAFE Ghostscript DLL
主要背景
我们实际上正在尝试获取 Ghostscript x64 DLL 的多线程版本,以便通过 Ghostscript .NET 使用它。该组件应该“允许在单个进程中同时运行多个 Ghostscript 实例”,但是,正如我们在我们的项目中检查的那样,在向应用程序发出并发请求之前工作正常。使用 Tasks 启动相同的方法可以复制相同的行为。在这两种情况下引发的错误描述是:
An error occured when call to 'gsapi_new_instance' is made: -100
即使它似乎与 .NET 没有直接关系,我也会 post 我们的 C# 方法代码示例,仅用于上下文化。
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, null);
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}
线程安全解决方案
开始调查,我们在 this post 上找到了这个 KenS 的答案,表明 Ghostscript DLL 必须使用 GS_THREADSAFE 编译器定义生成。
澄清一下,当我们使用 Ghostscript 9.52 x64 生成 PDF 时,我们需要为 Release 配置编译这个 x64 DLL。在尝试使用 Visual Studio Community 2017 和 Visual Studio Community 2019 在 Windows 10 x64 机器上编译 Ghostscript 源代码后,我们终于成功地构建并生成了所有项目(仅使用 VS Community 2019)而无需GS_THREADSAFE 参数,只是为了确认编译正常,我们检查 DLL 和可执行文件是否正常工作。对于这个过程,我们考虑了在 Ghostscript official documentation.
中发现的所有内容
由于我们没有其他指南来包含这个 GS_THREADSAFE 参数,我们按照 this solution 中给出的说明进行操作,包括 XCFLAGS="-DGS_THREADSAFE=1"
on nmake build commands, usign this sentence for 全部重建 选项:
cd .. && nmake -f psi\msvc32.mak WIN64= SBR=1 DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 && nmake -f psi\msvc32.mak WIN64= DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 bsc
这种方法在构建过程中会出现错误:
Error LNK2019 unresolved external symbol errprintf_nomem referenced in
function gs_log_error File \mkromfs.obj 1
看起来,文件 mkromfs.c 有一个名为 的方法errprintf_nomem,设置GS_THREADSAFE时找不到
问题
1 - 是否有包含编译为 THREADSAFE 的 x64 DLL 的 Ghostscript public 版本?
而且,如果不是(这就是我的猜测...)
2 - 是否可以在不更改源代码的情况下使此 DLL 成为线程安全的?
3- 任何人都可以提供一步一步的指南或演练来使用 GS_THREADSAFE 使用 Visual Studio (甚至任何其他可能的替代方法)构建 x64 Ghostscript DLL 而不是 Windows 10 x64?
4 - 一些 post 谈论人们使用 Ghostscript .NET 管理多线程。我假设这些示例都使用 GS_THREADSAFE DLL...我们是否通过了任何其他解决方法?
提前致谢。
嗯,看来你是来寻求技术支持的。
您显然想在商业项目中使用 Ghostscript,实际上有人可能会说您想要 Ghostscript 的企业版。大概您不想更改源代码以允许您使用开源许可证,因为您不想为商业许可证付费。
考虑到这一点,您的问题的答案是:
- 不,Ghostscript 开发人员实际上并未构建 thread-safe 版本的二进制文件。
- 目前没有。这可能是一个疏忽。
- 这将是一个技术支持问题,不能保证为免费用户提供技术支持,这是双许可证供应商说服人们接受商业许可证的少数几个杠杆领域之一。所以我希望你能理解我不会提供那个。
- 据我所知,没有。
为了总结所有这些问题,并作为未来开发人员遇到同样问题的指南,这些是我们迄今为止找到的答案:
AS @KenS 在他的回复中提到:“不,Ghostscript 开发人员实际上并没有构建 thread-safe 版本的二进制文件。”
此时此刻,显然不是,正如 this opened bug 上所报道的那样。
好像是商业许可支持的问题,我们就不再评论了。
再次感谢@HABJAN。我绝对收回我在问题中所说的话,因为 Ghostscript .NET 可以在 multi-threading 场景 上工作。下面是我们应用的解决方案,以防对某人有用。
基于 HABJAN 示例,我们为实现此目的所做的工作是创建自定义 class 以捕获 Ghostscript 日志记录:
protected class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr) : base(handleStdIn, handleStdOut, handleStdErr)
{
}
public override void StdIn(out string input, int count)
{
char[] userInput = new char[count];
Console.In.ReadBlock(userInput, 0, count);
input = new string(userInput);
}
public override void StdOut(string output)
{
//log
}
public override void StdError(string error)
{
//log
}
}
对于我们之前的方法,我们简单地包括对此的调用 class 这避免了同时执行多个任务时的错误:
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, new ConsoleStdIO(true, true, true));
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}
主要背景
我们实际上正在尝试获取 Ghostscript x64 DLL 的多线程版本,以便通过 Ghostscript .NET 使用它。该组件应该“允许在单个进程中同时运行多个 Ghostscript 实例”,但是,正如我们在我们的项目中检查的那样,在向应用程序发出并发请求之前工作正常。使用 Tasks 启动相同的方法可以复制相同的行为。在这两种情况下引发的错误描述是:
An error occured when call to 'gsapi_new_instance' is made: -100
即使它似乎与 .NET 没有直接关系,我也会 post 我们的 C# 方法代码示例,仅用于上下文化。
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, null);
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}
线程安全解决方案
开始调查,我们在 this post 上找到了这个 KenS 的答案,表明 Ghostscript DLL 必须使用 GS_THREADSAFE 编译器定义生成。
澄清一下,当我们使用 Ghostscript 9.52 x64 生成 PDF 时,我们需要为 Release 配置编译这个 x64 DLL。在尝试使用 Visual Studio Community 2017 和 Visual Studio Community 2019 在 Windows 10 x64 机器上编译 Ghostscript 源代码后,我们终于成功地构建并生成了所有项目(仅使用 VS Community 2019)而无需GS_THREADSAFE 参数,只是为了确认编译正常,我们检查 DLL 和可执行文件是否正常工作。对于这个过程,我们考虑了在 Ghostscript official documentation.
中发现的所有内容由于我们没有其他指南来包含这个 GS_THREADSAFE 参数,我们按照 this solution 中给出的说明进行操作,包括 XCFLAGS="-DGS_THREADSAFE=1"
on nmake build commands, usign this sentence for 全部重建 选项:
cd .. && nmake -f psi\msvc32.mak WIN64= SBR=1 DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 && nmake -f psi\msvc32.mak WIN64= DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 bsc
这种方法在构建过程中会出现错误:
Error LNK2019 unresolved external symbol errprintf_nomem referenced in function gs_log_error File \mkromfs.obj 1
看起来,文件 mkromfs.c 有一个名为 的方法errprintf_nomem,设置GS_THREADSAFE时找不到
问题
1 - 是否有包含编译为 THREADSAFE 的 x64 DLL 的 Ghostscript public 版本?
而且,如果不是(这就是我的猜测...)
2 - 是否可以在不更改源代码的情况下使此 DLL 成为线程安全的?
3- 任何人都可以提供一步一步的指南或演练来使用 GS_THREADSAFE 使用 Visual Studio (甚至任何其他可能的替代方法)构建 x64 Ghostscript DLL 而不是 Windows 10 x64?
4 - 一些 post 谈论人们使用 Ghostscript .NET 管理多线程。我假设这些示例都使用 GS_THREADSAFE DLL...我们是否通过了任何其他解决方法?
提前致谢。
嗯,看来你是来寻求技术支持的。
您显然想在商业项目中使用 Ghostscript,实际上有人可能会说您想要 Ghostscript 的企业版。大概您不想更改源代码以允许您使用开源许可证,因为您不想为商业许可证付费。
考虑到这一点,您的问题的答案是:
- 不,Ghostscript 开发人员实际上并未构建 thread-safe 版本的二进制文件。
- 目前没有。这可能是一个疏忽。
- 这将是一个技术支持问题,不能保证为免费用户提供技术支持,这是双许可证供应商说服人们接受商业许可证的少数几个杠杆领域之一。所以我希望你能理解我不会提供那个。
- 据我所知,没有。
为了总结所有这些问题,并作为未来开发人员遇到同样问题的指南,这些是我们迄今为止找到的答案:
AS @KenS 在他的回复中提到:“不,Ghostscript 开发人员实际上并没有构建 thread-safe 版本的二进制文件。”
此时此刻,显然不是,正如 this opened bug 上所报道的那样。
好像是商业许可支持的问题,我们就不再评论了。
再次感谢@HABJAN。我绝对收回我在问题中所说的话,因为 Ghostscript .NET 可以在 multi-threading 场景 上工作。下面是我们应用的解决方案,以防对某人有用。
基于 HABJAN 示例,我们为实现此目的所做的工作是创建自定义 class 以捕获 Ghostscript 日志记录:
protected class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr) : base(handleStdIn, handleStdOut, handleStdErr)
{
}
public override void StdIn(out string input, int count)
{
char[] userInput = new char[count];
Console.In.ReadBlock(userInput, 0, count);
input = new string(userInput);
}
public override void StdOut(string output)
{
//log
}
public override void StdError(string error)
{
//log
}
}
对于我们之前的方法,我们简单地包括对此的调用 class 这避免了同时执行多个任务时的错误:
// Define switches...
string[] switchesArray = switches.ToArray();
using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
try
{
procesador.StartProcessing(switchesArray, new ConsoleStdIO(true, true, true));
byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);
return destinationFile;
}
catch (Exception ex)
{
throw ex;
}
finally
{
System.IO.File.Delete(sourceFile);
}
}