返回列表 发帖

[问题求助] powershell调用dll将汉字转为拼音

本帖最后由 小白龙 于 2023-3-14 13:36 编辑

本人对Powershell和C++都不太懂

我想将下面链接的代码, 编译成dll, 然后在powershell中调用dll中的函数, 把汉字转为拼音
https://www.cnblogs.com/tangxin-blog/p/5541635.html

对于同时精通PS和C++两种语言的大佬, 可能是小case, 期待大佬能指引一下, 大致写个所用到的软件或工具及实现的过程,注意事项等, 非常感谢

应该有现成的转拼音的DLL了, 我上面是想通过大佬的指引, 以后也能自己修改和编译dll

你自己写一个PS就可以了。保留他原来的CODE部分,用来识别编号;
对输入的字符串用GBK编码一个一个判断。若为一个字节则保留原字符,2个字节则高位码在前低位码在后,大于160则减去160再把高位码乖100合成4位数再去查CODE。若4位查不到则输出原字符,可能是符号之类。
QQ: 458609586
脚本优先 [PowerShell win10]

TOP

extern "C" _declspec(dllexport)void h2p(const char* szChinese)
{
    uint32_t bufLen = 0;
    char pinyinBuf[MAXBUFLEN] = { 0 };
    //const char* szChinese = "中华人民共和国 People's Republic of China";
    getPinyin(szChinese, pinyinBuf, MAXBUFLEN, &bufLen, enmPinyinMode_FirstUpper);
    printf("%s\n", pinyinBuf);
}COPY
$code=@"
using System;
using System.Runtime.InteropServices;
public static class Api{
[DllImport("C:/Users/Administrator/source/repos/test/x64/Release/test.dll")]
public static extern int h2p(String ss);
    }
"@
Add-Type -TypeDefinition $code
[Api]::h2p("我是中国人")COPY

TOP

直接编译成dll只能以p/invoke方式调用.为了兼容性,用msvc,软件就是visual studio(图形界面)或visual studio build tools(字符界面).注意要在编译选项给出导出函数或在源码需要导出的函数前加上
__declspec(dllexport)

想要在ps直接使用,需要转成c++/cli的代码并且以/clr的编译选项编译成dll,有点麻烦

其实也可以直接在ps里写个文字跟拼音的hashtable,然后索引就行了

(有多音字的存在,不管怎么样都不会100%准确)

TOP

回复 4# Five66


    多谢大佬指导, 我现在大致明白了思路, VS太大了, 有没有其它的编译小工具呢? 在PS中写函数, 感觉执行速度会慢, 应该没有调用dll快
:

TOP


QQ 20147578

TOP

本帖最后由 小白龙 于 2023-3-14 20:28 编辑

回复 3# pd1


    多谢大佬指导, 现在代码和事项都有了, 就差编译dll了, 我不装vs有别的方式编译DLL吗, 以前看到过文章可以用什么tcc编译器搞,但是不知道怎么搞

TOP

回复 6# czjt1234

多谢大佬指导, 这个贴子, 我主要是想学习下, 编译C或C++为DLL, 然后在PS中调用DLL的方法和事项

TOP

本帖最后由 小白龙 于 2023-3-14 20:33 编辑

回复 2# xczxczxcz

多谢大佬指导, 我懂的太浅了, 自己搞不了  有现成的轮子, 就不自己搞了

TOP

本帖最后由 小白龙 于 2023-3-14 20:34 编辑

回复 4# Five66


    大佬, 我对下面这句话不太懂, DLL能在PS下直接使用?  怎么直接使用, 有代码吗? 麻烦点也想尝试下, 有文章链接吗? 我想试试
想要在ps直接使用,需要转成c++/cli的代码并且以/clr的编译选项编译成dll,有点麻烦

TOP

回复 10# 小白龙

除了vs还可以使用gcc(mingw)或clang(llvm),vs因为包含各种平台跟目标平台(x86,x64,arm,arm64....)才这么大的,只能安装后自行精简

ps编译成可以直接使用dll,可以参考
https://learn.microsoft.com/zh-cn/previous-versions/ms235281(v=vs.120)
编译成dll后(只能使用msvc,即vs编译),ps里直接add-type之类添加dll就行了

TOP

回复 11# Five66

还有种方法,用C#生成一个调用C++的封装类的dll,ps里也可以直接使用

TOP

本帖最后由 went 于 2023-3-14 21:54 编辑

64位dll & 调用
pinyin.rar

TOP

回复 3# pd1
大佬能指导下吗?
我没有装VS,看了点教程用Tcc编译, 会报下面的错误,
tcc: undefined symbol 'isascii'
我把报错的(// 排除askii 码 )那几行代码删了, 能编译成功, 但是在PS中执行又报下面的错误
Add-Type : c:\Users\Administrator\AppData\Local\Temp\30bxsszt\30bxsszt.0.cs(4) : 无法识别的转义序列

下面是编译的C代码前面的部分, 贴全部就超长了
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#define EXPORT __declspec(dllexport)
#define MAXBUFLEN 1024
enum PinyinMode{
    enmPinyinMode_AllUpper = 0,        //全大写
    enmPinyinMode_AllLower,            //全小写
    enmPinyinMode_FirstUpper,        //首字母大写
};
const char* getPinyinByCode(uint32_t code);
void getPinyin(const char* szChinese,char pinyinBuf[],const uint32_t maxBufLen,uint32_t *bufLen,const uint32_t mode);
EXPORT void h2p(const char* szChinese)
{
    uint32_t bufLen = 0;
    char pinyinBuf[MAXBUFLEN] = { 0 };
    //const char* szChinese = "中华人民共和国 People's Republic of China";
    getPinyin(szChinese, pinyinBuf, MAXBUFLEN, &bufLen, enmPinyinMode_FirstUpper);
    printf("%s\n", pinyinBuf);
}
void getPinyin(const char* szChinese,char pinyinBuf[],const uint32_t maxBufLen,uint32_t *bufLen,const uint32_t mode)
{
    *bufLen = 0;
    uint8_t ucHigh, ucLow;
    uint32_t code,i,j;
    const uint32_t chineseLen = strlen(szChinese);
    for (i = 0; i<chineseLen;++i )
    {
        uint8_t c = szChinese[i];
        // 排除askii 码
        if (isascii(c))
        {
            pinyinBuf[(*bufLen)++] = c;
            continue;
        }
        ucHigh = (uint8_t)szChinese[i];
        ucLow  = (uint8_t)szChinese[++i];
        if ( ucHigh <= 0xa0 || ucLow <= 0xa0 )
        {
            continue;
        }
        else
        {
            code = (ucHigh - 0xa0) * 100 + ucLow - 0xa0;
        }
        const char* pBuf = getPinyinByCode(code);
        for (j = 0; j < strlen(pBuf) && (*bufLen) < maxBufLen; ++j)
        {
            char cc = pBuf[j];
            switch(mode)
            {
            case enmPinyinMode_AllUpper:break;
            case enmPinyinMode_AllLower:cc = tolower(cc);break;
            case enmPinyinMode_FirstUpper:if(j!=0)cc = tolower(cc);break;
            }
            pinyinBuf[(*bufLen)++] = cc;
        }
    }
}
}COPY

TOP

回复 13# went

多谢大佬, 您用什么编译的? 我用tcc编译会报上面的错误, 另外我的电脑是32位的, 应该用不了64位dll

TOP

返回列表