jsoncpp json压缩转换字符串写法

背景

自己用jsoncpp已经几年了,一直都用 toStyledString来转换字符串,但这种格式化字符串,但如果用来传递数据,那么有许多多余数据,所以我一直想找到压缩的字符串,网上找了一些关键词基本都没有找到,突然有一天我直接看一下jsoncpp的源代码。

过程

  1. 查看toStyledString 代码
    
    std::string 
    Value::toStyledString() const
    {
    StyledWriter writer;
    return writer.write( *this );
    }
题外话:用vscode看代码还是蛮舒服的
jsoncpp 定义styledWriter ,然后我发现他有一个FastWriter

class JSON_API FastWriter : public Writer
{
public:
FastWriter();
virtual ~FastWriter(){}
void enableYAMLCompatibility();
public:
virtual std::string write( const Value &root );
private:
void writeValue( const Value &value );

  std::string document_;
  bool yamlCompatiblityEnabled_;

};

然后看了一下write就是我想要的压缩的字符串。

## 使用

Json::Value root;
root["id"] = "test";
root["name"] = "fish";
FastWriter fast_writer;
std::string result = fast_writer.write(root);


## 总结
jsoncpp 我用几年前的老版本,看github 貌似重写了,不过目前自己够用,新不代表就好。。
jsoncpp 我的用版本不支持 uint_64,我只能用std::string 来代替

vs2019 c++开发软件独运行[运行库文件抽取]

背景

用vs2019 c++开发软件,发行版本需要运行库,因为别的电脑不一定安装运行库,所以要特别处理

方案

  1. 编译的exe,c++运行库设置MT(静态模式),代码集成在你的exe中
    1. 导致exe变大
    2. 其他第三方库可能冲突【可能第三方库需要改变编译模式】,常见冲突在这里
    3. 存在多份运行库代码,增大安装包体积
    4. 简单
  2. 需要动态库DLL 放在exe执行目录
    1. 需要复制多个DLL,所以要知道依赖哪些库
  3. 安装运行库
    1. 增加安装包体积
    2. 安装运行库万一冲突,还可能失败【对于阉割系统,太多麻烦的事情】
    3. 增加安装时间

      选择

      主流方案都选择第二种

      常见需要复制文件,打开vs2019,然后跳出任务管理器,找到对应进程,然后打开所在的目录


目录跳到IDE这一层

进行搜索
vcruntime140.dll
msvcp140.dll
ucrtbase.dll
api-ms-win-crt-conio-l1-1-0.dll 打开这个位置所有api-全部复制出来,懒得一个一个找。

基本大部分项目足够,如果软件还报错,他会提示,你自己慢慢复制就可以了,其他的版本vs也是这么慢慢查找。

备注

一定要放在exe同级目录,因为window搜索动态目录是这样子(非系统DLL优先级是当前目录最大)。
vs2019 多了好多api,貌似2015以后微软优化运行库,我看了一下文档,没有看出什么特别的地方,现在只记得它进行优化。。。

POCO c++ 库 string to utf8 string

背景

POCO 是一款全面的c++开发框架,基本设计大部分常见使用功能,但没有直接std::string to utf8 string代码,网上找了好久找到(有Unicode std::wstring 转换utf8 std::string)

代码

Poco::Windows936Encoding cp936;
Poco::UTF8Encoding utf8;
Poco::TextConverter converter(cp936, utf8);
std::string src = "你好";
std::string dst;
converter.convert(src, dst);

说明

Windows936Encoding 包含gbk,所以可以用来转换中文到utf8 std::string, 这个东西我是从github 上找到有关的问题,所以记录一下,方便窄字节字符串转换成utf8编码。主要还是c++ 基础库太不够用了,学术太重,不够落地,导致c++ 一个好用的网络库都要用第三方的,或者自己封装。对于自己开发,什么都要自己,对新手太不够友好了,所以建议c++ 用通用第三方库,加快开发速度,降低门槛。或者换其他的语言,没有必要浪费时间在一些跟产品没有关系的东西上。因为语言就是为了解决某种需求,而不是为了编程而编程。

parsec 使用遇到软件问题

背景

自己已经使用parsec远程办公一段时间,写代码非常流畅,基本和本地写代码差不多,国产的远程软件达不到,向日葵,todesk都达不到这么流畅,不过使用遇到过黑屏的问题。

问题

黑屏

  1. 向日葵远程开启黑屏,偶尔启动电脑会导致parsec连接上黑屏,重启几次可能恢复,后面我直接关闭了默认连接开启黑屏功能,这个问题就解决了。
  2. 笔记本盖子没有打开,导致连接黑屏,必须笔记本盖子开启,向日葵也会显示不正常,但能用。

卡住

  1. 点击nvdia geforce 软件 就会卡住,我只能用向日葵远程点击这个弹窗就恢复正常

parsec与其他远程一起用

  1. 向日葵配合他开机棒,用远程开机【向日葵开机启动】
  2. 开机后,向日葵远程控制登陆账号然后启动parsec软件
  3. 文件传送用向日葵或者一些临时文件发送的网站,比喻奶牛快传【现在要注册才能发送】
  4. 如果卡住了,用向日葵点击一下

补充

如果没有实体显示器,可以用网上虚拟显示器方法,具体可以看之前的文章。。。

其实我没有明白,parsec能够低延迟,应该主要还是显卡编码加成,网络协议应该没有那么重要。

scrcpy 实现全选功能ctrl+a 输入法

背景

之前实现输入法功能,然后去android keyevent文档上找是否这样子,结果毛都没有,然后看scrcpy上面也没有看到单独一个函数是实现全选,后面想了好久是不是就是实现ctrl+a 这个按键呢?后面果然发现确实是这样子

知识点

在scrcpy 他实现按键时候传递metaState 这个属性值,我自己没有实现,然后看了一个关键词 AMETA_CTRL_LEFT_ON,然后搜索到这个对应值,所以只要模拟A时候设置一下metaState

PC代码

bool WindowsUI::HandleSelectAll(const SDL_KeyboardEvent& ev)
{
    if (ev.keysym.sym == SDLK_a && (ev.keysym.mod & KMOD_LCTRL) == KMOD_LCTRL) {
        //a + ctrl
        //AMETA_CTRL_LEFT_ON 0x2000
        m_contronl_net->SendKeyEvent(29, 0x2000);        //全选
        return true;
    }
    return false;
}

android 代码

    private void handleKeyCodeMessage(JSONObject data) throws JSONException{
        int key_code = data.getInt("key_code");
        int meta_state = data.getInt("mode");
        actionImplement.keyEvent(key_code, meta_state, false);
    }

        private void sendKeyEvent(int inputSource, int keyCode, int meteState, boolean longpress) {
        long now = SystemClock.uptimeMillis();

        EventFactory.injectKeyEventSelf(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, meteState,
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
        if (longpress) {
            EventFactory.injectKeyEventSelf(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, meteState,
                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
                    inputSource));
        }

        EventFactory.injectKeyEventSelf(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, meteState,
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
    }

我模拟按键跟scrcpy不一样,感觉简单一些,因为我抄的是adb 实现模拟,看一眼就特别清晰。。
现在自己用协同工具非常舒服了,我现在就缺少文件传送了,这个东西还是非常方便。主要平时自己还不到图片发送,主要看手机上APP的东西。

scrcpy 类似软件实现思路与探索(初版)

背景

当初看到这个scrcpy工具觉得非常神奇,不知道怎么实现,我对某种业务具体实现特别感兴趣,但我对编程语言没有太多兴趣,对一些用不到算法也特别不感兴趣。后面自己研究一段时间,然后结合scrcpy源代码和其他产品大概实现思路,总结scrcpy 通过app_process实现技术。

技术

  1. app_process 技术
    这个是根本技术,自己实现adb命令功能代码,为什么我们不直接用adb 实现呢?以前一些云控技术用的adb 命令,因为adb 命令会创建进程,对于非常频繁的行为,性能太低。同时跨进程,没有直接源码实现。所以用app_process技术,因为可以通过反射实现adb 代码实现,那你会想我反射不一定要app_process,直接在android 代码反射也可以,反射代码可以写,但没有权限或者说权限不够,模拟点击调用会失败,通过源代码发现他需要系统的权限。如果不走app_process,可以root手机达到反射条件。
  2. 反射
    怎么反射,对于新手完全找不到方向,你看scrcpy代码,你也不知道为什么他们能找到,后面我想既然他们反射实现的adb命令,应该看了android 命令实现代码,果然我在 android 源代码找到有关代码,那么我们方向找到了,只要找命令源代码,那么基本就能反射出来。
  3. android 怎么编码或者怎么截图
    1. 反射截图命令
      我最开始也是这么想的,反射命令截图,FPS可以达到30帧样子,虽然达不到60fps基本作为协作工具完全可以了
    2. android h264 编码
      1. 这个通过编码成h264,获取一个buffer就投递给PC端【直播】
      2. 这里难点不熟悉android 编码代码,直接自己搜索一下这方便代码,完全写一个直播丢给PC,不用反射,编码直接申请权限,调用代码就可以了。
  4. 网络通信
    1. scrcpy用原生socket,然后协议用二进制自定义协议

      我觉得不是很有必要,如果真的为什么节约通信大小,直接用protobuf就好了,毕竟动态的varint还是比较节约内存,不过对于简单协议,用什么都可以,我只是提一嘴。

    2. 我自己用websocket+JSON 来通信

      不用自己切包,JSON解析扩展性高,对于命令来说,这一点协议没有消耗无所谓。

    3. 视频流,直接丢给单独接受视频端口,如果有服务接入,那么考虑东西会多一些。
  5. PC端
    1. 视频解码

      业界ffmepg 开发库,按照官方解码视频就好

    2. 渲染
      1. 网页

        感觉渲染速度达不到,貌似都是解决mp4 标签来做的,都会缓存,我没有试过,底层解码成图片,然后投递给网页,我最开始截图成PNG,然后给网页,貌似性能不错。

      2. SDL

        scrcpy就是这么写的,我网页慢,也用sdl,只是整个写法完全自己写的,没有借鉴scrcpy,因为他的跨平台而且用纯c,用大量函数指针来模拟面向对象写法,我直接用c++写的 windows代码,用原生win32 没有用任何其他的,mfc,或者 duilib或者其他的界面。

  6. 业务代码
    1. 点击实现
      1. android 反射实现代码
      2. PC 界面与 手机界面比例,然后计算在android 真实的坐标
    2. 按键实现
      1. androi 反射 input 命令代码
      2. SDL 处理按键操作
        1. 快捷键处理

          要判断什么时候快捷键,什么单独按键,所以这么设计一些业务代码蛮多,我自己重写几次才写好,所以没有相信那么简单。keyup keydown 什么时候处理,什么时候不处理。

        2. keydown可能够处理连续按键,keyup 不会触发,所以处理单独按键要响应keydown,而不是keyup触发,否则无法实现一个按键一直按着,触发多次逻辑,
  7. android旋转
    1. android 反射监听手机旋转,旋转就重新创建编码,PC端检测手机传过来的编码变化就要重新处理buffer,我开始不知道,所以旋转导致ffmepeg解码报错,我都不知道什么原因。

      总结

      上面基本是scrcpy基本逻辑需要技术点,下篇文章我会说怎么找到adb 命令对象实现代码。
      这篇文章只是从我大脑技术一下子写完,总结自己疑惑。

      写博客只是养成一个长期习惯,从而实现思考的复利,博客加广告只是看是不是有真人看我的博客,其实有没有都不是那么重要(有更好),现在总共靠广告赚了3美元了,100美元提现,感觉这辈子应该看不到了。。

如果我的博客对你真有帮助,那我也稍微欣慰一下。。。
突然想起来,我当初写博客只是想看一下,互联网从0到1链接,感受互联的感觉。目前已经感受到了,发现google搜索带过来量,自己基本没有放过外联。不知道他怎么跑过来的。

android app_process 反射实现广播

背景

因为Scrcpy 目前版本不支持输入法,自己的协同工具为了方便自己使用,增加直接在windows用输入法,而不是直接Keycode方式,这样子体验好很多。

使用输入法

我这里直接用了网上开源 ADBKeyBoard 解决 不能支持uncode编码问题(因为adb input 不支持unicode,如果直接反射也是不可以使用的【这样子中文就有很大问题】),但这个实现用广播,原来scrcpy没有反射广播,于是我看 adb shell am broadcast -a 对应在android cmd 里面目录代码,看他用了broadcastIntent 方法

反射 Android12 broadcastIntent

public void sendBroadcast(Intent intent){
        //IntentReceiver receiver = new IntentReceiver();

        try {
            Class cls = Class.forName("android.app.IApplicationThread");
            //   public int broadcastIntent(IApplicationThread caller,
            //2352            Intent intent, String resolvedType,  IIntentReceiver resultTo,
            //2353            int resultCode, String resultData, Bundle map,
            //2354            String requiredPermission, int appOp, boolean serialized,
            //2355            boolean sticky, int userId)
            Method method = manager.getClass().getMethod("broadcastIntent",cls, Intent.class, String.class, IIntentReceiver.class, int.class, String.class,
                    Bundle.class, String[].class, int.class, Bundle.class,boolean.class, boolean.class, int.class);

            Object objString = method.invoke(manager, null,intent, null, null, 0, null, null, null, -1, null, true, false, android.os.Process.myUid()/100000);
            Ln.i("调用完成:" + objString.toString() );
        } catch (ClassNotFoundException e) {
            Ln.e("notfound" + e.toString());
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            Ln.e("InvocationTargetException" + e.toString());
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            Ln.e("NoSuchMethodException" + e.toString());
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            Ln.e("IllegalAccessException" + e.toString());
            e.printStackTrace();
        }
        //manager.getClass().getMethod()
        /*this.broadcastIntent(null, intent, null, null, 0, null, null, null, true, false,
                Binder.getOrigCallingUser());*/
        //receiver.waitForFinish();
    }

这个参数挺多的,不能版本参数不一样,所以要看android的源代码,这样子我在windows 启动SDL 输入法
响应input

        if (event.type == SDL_TEXTINPUT) {
            HandleInput(event); //直接发送网络请求到android里面,然后调用反射发送广播
            continue;
        }

这样子就是简单实现app_process 反射广播

难点

  1. 一开始不不知道怎么弄,所以要看adb 里面发送广播的实现,scrcpy 实现本质也是看android adb源代码,所以协同工具本质就是自己实现一个adb在 app_process,同时app_process 启动进程使用shell权限,所以能反射一些高级命令,模拟点击就是具有adb权限,如果apk 具备这样子权限,那么也可以直接反射调用点击命令。
  2. 参数好多,如果不熟练很容易反射报错。今天我实现反射shellCommand 命令(高版本android 实现命令新代码),实例化带一个参数报错,结果我传入null,默认转换空参数数组,导致实例化失败。。
  3. 不同android版本反射参数有区别,我这里只是反射自己用的,所以要注意。

补充

后面可以说一下Scrcpy 开发思路,同时重点说一下服务怎么反射

scrcpy 为什么要在旋转停止发送视频流

问题

我自己写了电脑控制手机协同(借鉴Scrcpy),但是自己偶尔会出现花屏(屏幕会出现残影)

排查

1:通过错误我找到无效数据包,但不知道为什么会无效,我把pc c++代码看了一下与sdl官方代码对比一下修复几个地方可能导致丢包的逻辑。

2:我发现屏幕旋转后,然后回到桌面,很容易出现花屏,因为我看过scrcpy代码,我发现他旋转时候会停止发送数据包,而我是没有处理

while (!consumeRotationChange() && !eof) {
            //这里是一直等待,所以这里很容易出现卡住,然后buffeer
            //是之前的surface的,旋转就导致宽度和高度不一样,导致前后不对
            int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, -1);
            eof = (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
            try {
                if (consumeRotationChange()) {
                    // must restart encoding with new size
                    //这里跳出来,
                    break;
                }
                if (outputBufferId >= 0) {
                    ByteBuffer codecBuffer = codec.getOutputBuffer(outputBufferId);

                    if (sendFrameMeta) {
                        writeFrameMeta(fd, bufferInfo, codecBuffer.remaining());
                    }

                    IO.writeFully(fd, codecBuffer);
                    if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                        // If this is not a config packet, then it contains a frame
                        firstFrameSent = true;
                    }
                }
            } finally {
                if (outputBufferId >= 0) {
                    codec.releaseOutputBuffer(outputBufferId, false);
                }
            }
        }

旋转会重新创建surface,这样子采集的数据不一样,所以会出现数据包错误。。。

总结

很多时候有现成的产品作为参考,可以避免很多坑,但如果自己不写,为什么这么是不知道真正的原因的。

浏览器自动删除指定网址历史记录插件

背景

自己访问一些网址,关闭标签或者关闭浏览器不会出现历史记录里面。

 插件

DynamicHistory

在chrome商店可以找到。

https://chrome.google.com/webstore/detail/dynamichistory/ehkdegpnplleadlmjoaidmjiabocgpok

https://www.chajianxw.com/product-tool/42001.html
这个是国内访问,我没有下载,只是搜到了,你可以下载试试,具体安装方法都是通过开发者模式进行安装,这种扩展网站都有写怎么安装的,你按照图片就可以了。

使用


点击插件,然后在上面框输入网址,我用* ,代表任意google的网址都不会记录。

其他的样式,自己可以在插件选项设置,主要是在显示被历史删除的网址的样式,标题是不一样的。
我自己都去掉了,这个看自己喜好

notepad++ 替代产品 everedit

背景

自己笔记本软件一直都是用notepad++,我喜欢他的多标签和多个文件搜索功能,但由于这个作者一直都有政治倾向,所以想找一款可以替换notepad++的软件,因为vscode比较重,所以我直接排除了,找几个几款都不是很满意,要么没有我想要的功能,要么就是太重。【vscode 用在写nodejs 或者网页时候】

everedit

我在搜索找到了everedit,而且他是国产的软件,同时支持我多标签自动保存和文件搜索功能,同时还有其他的为开发装备的扩展,我自己已经用几周,感觉非常满意,暂时没有找到其他的问题。虽然他高级功能收费,但我基本用不到高级功能,同时他应该是纯c开发,然后界面win32开发,因为我用vs 打开资源,可以看到他的对话框资源,同时没有引用mfc的dll,也没有用c++ 运行库,那么它可能纯c写的。而且文件大小都很小。

有时候真觉得纯c开发的软件真的小而美,用高级语言开发东西反而只是大了

everedit介绍

标签临时缓存

他默认多个标签不会缓存,必须自己在设置里面进行设置。

搜索

这个基本和nopted++ 支持多个

它高级查找还支持匹配行和非匹配行,统计行数,这个非常适合开发用,我感觉作者产品理解能力还是很强的。他文件路径搜索可以自己去在查找菜单里面,界面开发还是非常清晰,我感觉比notepad++还更加清晰。

base64使用

选择要base64的文字,点击菜单工具的里面base64就可以进行编码与解码了,这个功能非常方便,如果某个文件要base64,那么直接权全选然后点击。

hex 二进制显示

这个自带二进制显示,然后右键可以直接复制16进制的字符串,这个对我非常方便,我以前用Hex专门工具,这样子就不需要了。

总结

我目前只用了上面这几个功能,其他功能暂时我没有用到,等我再用一段时间,如果我还觉得非常好友,去买一个永久激活码支持一下作者,虽然我用不到他的收费高级功能,算是支持国产软件。
~~
貌似30天的试用期,试用期过期会弹出购买对话框,然后点击确定就可以正常使用,我目前还没有过30天,等后面看具体情况,没有高级高能收费这个说法。。。~~
大概一个月试用期,过期了会提示,然后就无法使用,目前我已经购买,但新建标签的bug一样存在,如果希望免费,这款不适合你,感觉目前比较合适也就vscode了,虽然重了一点点

官网

http://www.everedit.cn/

问题

我现在使用,发现新建标签会出现重复,比喻标签1,我关掉程序,然后再新建标签,还会创建标签1,看起来没有什么,但如果搜索第二个标签1时候,点击搜索内容会跳到第一个标签,导致错乱,感觉非常不爽,我不知道这个bug怎么会有,稍微用一下就应该重现。。

我暂时每次新建标签时候,如果重复直接关闭那个重复就不会出现这个问题,但感觉不爽,如果有时间直接给他打一个补丁,或者写一个插件解决这个问题,实在有点膈应自己,目前还没有过期,我还没有购买这个软件,我想想看看过期会不会弹出购买对话框